使用玩笑/酶测试调用setState的异步componentDidMount

时间:2018-07-15 19:21:43

标签: reactjs jestjs enzyme

我的async componentdidmount中包含以下代码:

async componentDidMount() {
    try {
        let responseText = await API.Licensing()
        this.setState({ html: responseText })
    } catch (e) {
        this.setState({ html: 'Error Fetching Licensing Info' })
    }
}

我一直对如何在此处测试setstate感到困惑,因为互联网上的大多数示例都使用promise then / catch,而这个示例使用try / catch async / await。

测试结果如何?

2 个答案:

答案 0 :(得分:4)

import React from "react";
import {
    shallow
} from "enzyme";
import axios from "axios";
import App from "./App";

jest.mock("axios");

it("fetches html", done => {
    const responseText = 'some text';
    axios.get.mockResolvedValueOnce(responseText);
    const wrapper = shallow( < App / > );

    setImmediate(() => {
        expect(wrapper.state().html).toBe('some text');
        done();
    });
});

it("transmits a useful message when fetching is not successful", done => {
    axios.get.mockImplementation(() => Promise.reject(new Error('error')))

    const wrapper = shallow( < App / > );

    setImmediate(() => {
        expect(wrapper.state().html).toBe("error");
        done();
    });
});

我想您可以用上面的 API 代替 axios 。您需要自己尝试。像这样:

import API from './API';

jest.mock("API");

... API.Licensing.mockResolvedValueOnce(responseText);

另一件事是,您可能不需要在那里的 done 参数,因为api响应被打断了,但是比后悔更安全!也需要检查一下这个:)(由于好奇,我必须设置一个项目来检查一下……)

PS:对于多个Promise,您只需要存根api响应,以根据需要更改 mockResolvedValueOnce 即可。在这里检查:https://jestjs.io/docs/en/mock-function-api.html

说明:模拟API响应并简化组件。然后,您需要在setImmediate函数中进行所有检查。老实说,将函数放置在什么位置都没有关系。如果您感到好奇,请尝试将其放在测试块的顶部。它总是在所有promise和callbacks解决之后最后执行。或者,您可以将process.nextTick或setTimeout与0时间参数一起使用。您可以在以下的nodeJS文档中找到更多信息:https://nodejs.org/en/docs/guides/event-loop-timers-and-nexttick/

基本上,您可以利用JS事件循环的不同队列,计时器回调等

答案 1 :(得分:0)

可能看起来像这样

test('Sets html to state', async () => {
    // Mock your api here...

    // using enzyme
    const component = await shallow(<YourComponent/>)

    // Waiting for all the promises in `componentDidMount` to resolve
    // max `i` may vary, it depends on the number of 'awaits' in  your code
    for (let i = 0; i < 9; i++) {
      await component.update()
    }

    expect(component.state('html')).toBe('someHtml')
})