【问题标题】:How to unit test promise rejection in React and Jest如何在 React 和 Jest 中对 Promise 拒绝进行单元测试
【发布时间】:2019-06-08 18:42:37
【问题描述】:

我正在尝试为反应组件编写单元测试。这是一个相当标准的组件,它调用一个 promise-returning 方法并使用 'then' 和 'catch' 来处理分辨率。我的测试试图验证它是否在 promise 被拒绝时调用了正确的方法,但是尽管遵循了我认为是标准模式的方法,但我无法开玩笑地验证调用。我在这里列出了相关文件,并且还提供了一个 github 示例,该示例链接在问题的底部。该示例只是一个使用 npx 创建的新反应应用程序,并添加了以下文件。

这是我的示例组件:

import React from 'react';
import api from '../api/ListApi';

class ListComponent extends React.Component {

    constructor(props) {
        super(props);
        this.fetchListSuccess = this.fetchListSuccess.bind(this); 
        this.fetchListFailed = this.fetchListFailed.bind(this); 

    }

    fetchList() {
        api.getList()
        .then(this.fetchListSuccess)
        .catch(this.fetchListFailed);
    }

    fetchListSuccess(response) {
        console.log({response});
    };

    fetchListFailed(error) {
        console.log({error});
    };

    render() {
        return(<div>Some content</div>);
    };
}

export default ListComponent;

这是 api 类(注意,如果您运行应用程序,则该 api 不存在,例如,它就在这里):

const getList = () => fetch("http://someApiWhichDoesNotExist/GetList");

export default { getList };

这是测试用例:

import ListComponent from './ListComponent';
import api from '../api//ListApi';

describe('ListComponent > fetchList() > When the call to getList fails', () => {
    it('Should call fetchListFailed with the error', async () => {

        expect.hasAssertions();

        //Arrange
        const error = { message: "some error" };
        const errorResponse = () => Promise.reject(error);
        const componentInstance = new ListComponent();

        api.getList = jest.fn(() => errorResponse());
        componentInstance.fetchListFailed = jest.fn(() => { });

        //Act
        componentInstance.fetchList();

        //Assert
        try {
            await errorResponse;
        } catch (er) {
            expect(componentInstance.fetchListFailed).toHaveBeenCalledWith(error);
        }

    });
});

问题是测试没有执行 catch 块,所以在这种情况下,expect.hasAssertions() 没有通过测试。谁能帮我理解 catch 块没有执行?在 try 块中包装 await 并在 catch 中声明似乎是 docs 中的标准模式,但我对 Js 和 React 还很陌生,显然做错了什么。

这是 GitHub 上的 sample project。任何帮助将不胜感激 =)

【问题讨论】:

    标签: javascript reactjs unit-testing jestjs es6-promise


    【解决方案1】:

    在您的控制台中:

    const errorResponse = () => Promise.reject();
    await errorResponse;
    //() => Promise.reject()
    

    您正在等待一个函数,而不是调用该函数的结果。你想:

    await errorResponse();
    

    编辑:

    除此之外,您的其余测试令人困惑。我相信您实际上想测试调用组件的 fetchList 方法时会发生什么,我假设它失败了。所以你需要在你的测试中调用它,并等待它的响应:

    1. 更新组件的 fetchList 方法以返回承诺。
    2. await componentInstance.fetchList() 而不是 await errorResponse()
    3. 因为你catchfetchList 中的错误你永远不会输入catchtry...catch 所以你的最终测试应该是这样的:

    测试:

    //Arrange
    const error = { message: "some error" };
    const errorResponse = () => Promise.reject(error);
    const componentInstance = new ListComponent();
    
    api.getList = jest.fn(() => errorResponse());
    componentInstance.fetchListFailed = jest.fn(() => { });
    
    //Act
    await componentInstance.fetchList();
    expect(componentInstance.fetchListFailed).toHaveBeenCalledWith(error);
    

    组件:

    fetchList() {
        return api.getList()
        .then(this.fetchListSuccess)
        .catch(this.fetchListFailed);
    }
    

    【讨论】:

    • 嗨,亚当。我在 await errorResponse 之后添加了括号,并且它现在确实在测试中执行了 catch 块,但是断言失败,说明没有调用 componentInstance.fetchListFailed?我觉得这有关系,你有什么建议吗?
    【解决方案2】:

    我的两分钱,我自己在一个 React 原生应用程序中的案例:

    在我的组件中我有:

      const handleRedirect = React.useCallback(() => {
        client.clearStore()
          .then(navigation.push('SomeScreen'))
          .catch(e => logger.error('error', e));
      }, []);
      
    

    我的测试是这个,我想测试promise是否被拒绝:

    it('should throw an exception on clearStore rejected', async () => {
        const client = {
          clearStore: jest.fn()
        };
    
        const error = new Error('clearStore failed');
    
        client.clearStore.mockReturnValue(Promise.reject(error));
    
        expect.assertions(1);
        await expect(client.clearStore())
          .rejects.toEqual(Error('clearStore failed'));
      });
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-08-17
      • 2020-10-03
      • 1970-01-01
      • 2020-07-24
      • 1970-01-01
      • 2017-10-20
      • 2017-12-01
      • 1970-01-01
      相关资源
      最近更新 更多