如何在React和Jest中对诺言拒绝进行单元测试

时间:2019-01-14 18:32:52

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

我正在尝试为react组件编写单元测试。这是一个相当标准的组件,它调用了承诺返回方法,并使用“ 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 docs中将await包裹在try块中并在catch中进行断言似乎是一种标准模式,但是我对Js和React还是很陌生,显然做错了什么。

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

2 个答案:

答案 0 :(得分:4)

在您的控制台中:

tableView.beginUpdate()
tableView.endUpdate()

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

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

编辑:

除此之外,其余的测试令人困惑。我相信您实际上是想测试调用组件的await errorResponse(); 方法时会发生什么,但失败了。因此,您需要在测试中调用它,然后等待它的响应:

  1. 更新组件的fetchList方法以返回承诺。
  2. fetchList而非await componentInstance.fetchList()
  3. 因为您await errorResponse()中的错误catch,所以您永远不会输入fetchListcatch,因此最终测试应如下所示:

测试:

try...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);

答案 1 :(得分:0)

我的两分钱,在React本机应用程序中有我自己的情况:

在我的组件中,我有:

 let syncError = error as! SyncError
 switch syncError.code {
 case .clientResetError:
 if let (path, clientResetToken) = syncError.clientResetInfo() {
 closeRealmSafely()
 saveBackupRealmPath(path)
 SyncSession.immediatelyHandleError(clientResetToken)
 }
 default:
 // Handle other errors...
 ()
 }
}```

我的测试是这个,我要在其中测试诺言是否被拒绝:

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