简体   繁体   English

如何在 ComponentDidMount 中模拟一个简单的 API 调用(Get Todos) - React + Typescript + Jest + Enzyme

[英]How to Mock A Simple API call (Get Todos ) in ComponentDidMount - React + Typescript + Jest + Enzyme

The app该应用程序

The app is a simple To Do List.该应用程序是一个简单的待办事项列表。 This App gets the todos from https://jsonplaceholder.typicode.com/todos?&_limit=5 .此应用程序从https://jsonplaceholder.typicode.com/todos?&_limit=5获取待办事项。

What I am trying to do我想做什么

Test an API call that is executed in ComponentDidMount in App.tsx .测试在 App.tsx 的 ComponentDidMount 中执行的API调用。

I want to mock the API call and return a list with two items.我想模拟 API 调用并返回包含两个项目的列表。 Then check if there are two items in the array or state.然后检查数组中是否有两项或state。

What files are important for you?哪些文件对您很重要?

  1. App.tsx (Component to be tested) App.tsx(待测组件)
  2. ToDoList.test.tsx (Contains test function) ToDoList.test.tsx(包含测试功能)

Small part of App.tsx to simplify it App.tsx 的一小部分以简化它

class App extends Component {

public state: IState = {
    items: [],
    value : 5,
    deleteItemParent : this.deleteItemParent
  };


  getAllTodos = async () => {
    await fetch(
      `https://jsonplaceholder.typicode.com/todos?&_limit=${this.state.value}`
    )
      .then((response) => response.json())
      .then((json) => {
        this.setState({ items: json })
      });
  };
  componentDidMount() {
    this.getAllTodos();
  }

componentDidUpdate(prevProps : any, prevState: any) {
  // Updates todo's if state changed
  if (prevState.value !== this.state.value) {
    this.getAllTodos();
  }
}

render(){
    return (
      <div className="App">
            <AddToDo addToDoParent={this.addToDo}/>
            <div>
                Todo's : {this.state.value}
            </div>
            <ToDoList items={this.state.items} deleteFromParent={this.deleteItemParent}/>
      </div>
    );
  }
}

ToDoListMock.test.tsx ToDoListMock.test.tsx

import React from 'react';
import { shallow , mount, ShallowWrapper} from 'enzyme';
import App from "../App";
global.fetch = jest.fn(() =>
  Promise.resolve({
    json: () => Promise.resolve(
      [
        {
          title: "Todo1",
          completed: false
        },
        {
          title: "Todo2",
          completed: false
        }
      ]
    )
  })
) as jest.Mock<any>

it("must contain 2 items in state after mock api call", async () => {
  const wrapper = shallow(<App />);

  await new Promise(res => setTimeout(res));
  // await jest.requireActual('promise').resolve()

  // Collect items from state
  const itemsFromState : any = wrapper.state('items');

  // Expect it to have a length of 2
  expect(itemsFromState.length).toBe(2);
})


The Error错误

Expected: 2 Received: 0预期:2 收到:0

EDIT编辑

SetupTests.ts设置测试.ts

/* eslint-disable import/no-extraneous-dependencies */
import Enzyme from 'enzyme';
import ReactSixteenAdapter from 'enzyme-adapter-react-16';
Enzyme.configure({ adapter: new ReactSixteenAdapter() });

I noticed an error while doing the test.我在做测试时注意到一个错误。 获取错误等待

There are a few things you have to change to make it work:您必须更改一些内容才能使其正常工作:

  • You forgot to trigger to fetch your notes as your component mounted by putting to componentDidMount :您忘记在组件挂载时触发获取您的笔记,方法是将其放入componentDidMount
componentDidMount() {
  this.getAllTodos();
}
  • Like you said, the data response is the list which is not a literal object, so you have to change your mock returning an array instead of literal object with todos property.就像你说的,数据响应是不是文字 object 的列表,所以你必须更改你的模拟返回一个数组而不是带有todos属性的文字 object。 But to make sure it runs well, we have to move beforeEach :但是为了确保它运行良好,我们必须移动beforeEach

beforeEach(() => {
 global.fetch = jest.fn(() =>
    Promise.resolve({
        json: () => Promise.resolve([ // Returns as an array here
            {
                title: "Todo1",
                completed : false
            },
            {
                title: "Todo2",
                completed : false
            }
        ])
    })
  ) as jest.Mock<any> 
})

  • Delay your test before getting the state since you have a mock promise need to be done:在获得 state 之前延迟测试,因为您需要完成模拟 promise:
it("must contain 2 items in state after mock api call", async () => {
  const wrapper = shallow(<App />);
  
  // Delay with either following ways to wait your promise resolved
  await new Promise(res => setTimeout(res));
  // await jest.requireActual('promise').resolve()

  // Collect items from state
  const itemsFromState: Array<any> = wrapper.state('items');

  // Expect it to have a length of 2
  expect(itemsFromState.length).toBe(2);
})

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何通过开玩笑和酶测试框架访问内部的反应组件和模拟api调用? - How to access internal pieces of react component and mock api call with jest & enzyme testing framework? 如何用jest和酶模拟React组件方法 - How to mock React component methods with jest and enzyme 如何嘲笑<appcontenxt.consumer>在 React 中使用 Jest 和 Enzyme</appcontenxt.consumer> - How to mock <AppContenxt.Consumer> in React using Jest and Enzyme React Enzyme - 测试`componentDidMount`异步调用 - React Enzyme - Test `componentDidMount` Async Call 如何为 componentDidMount() 编写单元测试用例并导出默认 connect(null, updateProps)(<componentname> ) 在 React 中使用 JEST/酶?</componentname> - How to write unit test case for componentDidMount() and export default connect(null, updateProps)(<ComponentName>) with JEST/Enzyme in React? 如何使用Jest和Enzyme为简单的React组件编写测试用例 - How to write a test case for a simple React component using Jest and Enzyme Jest / Enzyme | ComponentDidMount应该在什么时候不被调用 - Jest/Enzyme | ComponentDidMount doesn't get called when it should Jest 如何模拟 API 调用的实现 - Jest how to mock implementation of an API call 如何验证使用Jest和Enzyme在componentDidMount中调用console.log? - How to verify console.log was called in componentDidMount using Jest and Enzyme? React/Jest/Enzyme - 如何使用外部 API 测试表单提交? - React/Jest/Enzyme - How to test a form submission using an external API?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM