【问题标题】:Testing async componentDidMount that calls setState, with jest/enzyme使用 jest/enzyme 测试调用 setState 的异步 componentDidMount
【发布时间】:2018-12-23 09:23:32
【问题描述】:

我的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。

测试会是什么样子?

【问题讨论】:

    标签: reactjs jestjs enzyme


    【解决方案1】:
    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:对于多个承诺,您只需要根据您的需要更改 mockResolvedValueOnce 的 api 响应。在这里查看:https://jestjs.io/docs/en/mock-function-api.html

    解释:您模拟您的 API 响应并浅显您的组件。然后您需要在 setImmediate 函数中进行所有检查。老实说,你把这个函数放在哪里并不重要。如果你很好奇,试着把它放在测试块的顶部。在所有承诺和回调解决后,它总是在最后执行。或者,您可以使用带有 0 时间参数的 process.nextTick 或 setTimeout。您可以在此处的 nodeJS 文档中找到更多信息:https://nodejs.org/en/docs/guides/event-loop-timers-and-nexttick/

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

    【讨论】:

    • 如果您解释您的代码,您的答案会更好。 :)
    • 更好@Markus
    【解决方案2】:

    它可能看起来像这样

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

    【讨论】:

      猜你喜欢
      • 2016-11-13
      • 2018-08-31
      • 2019-06-25
      • 2020-01-20
      • 2020-03-15
      • 2019-03-18
      • 2022-01-18
      • 2016-06-25
      • 2021-04-14
      相关资源
      最近更新 更多