【问题标题】:How to Mock A Simple API call (Get Todos ) in ComponentDidMount - React + Typescript + Jest + Enzyme如何在 ComponentDidMount - React + Typescript + Jest + Enzyme 中模拟一个简单的 API 调用(获取 Todos)
【发布时间】:2021-02-25 15:03:46
【问题描述】:

应用程序

该应用程序是一个简单的待办事项列表。此应用从https://jsonplaceholder.typicode.com/todos?&_limit=5 获取待办事项。

我想做什么

测试在 App.tsx 中的 ComponentDidMount 中执行的 API 调用。

我想模拟 API 调用并返回一个包含两个项目的列表。然后检查数组或状态中是否有两项。

哪些文件对您很重要?

  1. App.tsx(要测试的组件)
  2. ToDoList.test.tsx(包含测试函数)

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

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);
})


错误

预期:2 收到:0

编辑

SetupTests.ts

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

我在进行测试时发现了一个错误。

【问题讨论】:

    标签: javascript reactjs typescript jestjs


    【解决方案1】:

    您必须进行一些更改才能使其正常工作:

    • 您忘记触发以获取您的笔记,因为您通过将组件安装到componentDidMount
    componentDidMount() {
      this.getAllTodos();
    }
    
    • 就像你说的,数据响应是不是文字对象的列表,所以你必须改变你的模拟返回一个数组而不是带有todos属性的文字对象。但是为了确保它运行良好,我们必须移动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> 
    })
    
    
    • 在获取状态之前延迟您的测试,因为您需要完成一个模拟承诺:
    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);
    })
    

    【讨论】:

    • 嘿,非常感谢!但它仍然没有工作:(。我确实忘记添加componentDidMount函数。项目的状态应该是json,因为如果我做了项目,实际的应用程序工作:json。我收到状态中的待办事项并且项目显示在屏幕。我还在测试文件中添加了延迟,但测试失败。预期:2 收到:0。我在帖子中编辑了代码:)。我还尝试了 await 的注释行。你还有什么想法吗?
    • 如果数据返回正确的东西,你模拟的数据很可能是错误的,它应该是一个数组而不是文字对象。我编辑了答案以指出正确的模拟
    • 嘿抱歉我的反应迟了,我会尽快回复。我像你说的那样编辑了代码,但仍然是同样的错误。我注意到我收到另一个错误:“TypeError:无法读取未定义的属性'then'”。我在帖子的屏幕截图中进行了编辑。
    • 我为你删除了复制的链接repl.it/@tmhao2005/Todo
    • 您好!啊哈哈我喜欢你知道我有一个问题;p。我有一个。我正在尝试测试一个组件。我的意思是 React-Testing-Library 和 Jest btw。如果您有时间回答它会很好:P。这是问题的stackoverflow链接:stackoverflow.com/questions/65811875/…
    猜你喜欢
    • 2019-08-30
    • 2022-01-19
    • 2021-04-14
    • 2019-05-12
    • 2019-03-18
    • 2021-02-14
    • 1970-01-01
    • 2019-08-12
    • 2018-12-23
    相关资源
    最近更新 更多