繁体   English   中英

如何在 React 和 Jest 中单元测试承诺拒绝

[英]How to unit test promise rejection in React and Jest

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

这是我的示例组件:

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 中断言似乎是文档中的标准模式,但我对 Js 和 React 相当陌生,显然我做错了什么。

这是 GitHub 上的示例项目 任何帮助将不胜感激 =)

在您的控制台中:

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

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

await errorResponse();

编辑:

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

  1. 更新组件的fetchList方法以返回承诺。
  2. await componentInstance.fetchList()而不是await errorResponse()
  3. 因为您在fetchList catch错误, fetchList您永远不会输入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);
}

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

在我的组件中,我有:

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

我的测试是这个,我想测试一下承诺是否被拒绝:

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

暂无
暂无

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM