如何使用Mocha进行单元测试以承诺重试的方式调用服务?

时间:2018-09-09 19:59:32

标签: reactjs unit-testing redux promise mocha

我在ReactJS项目中有一个调用通知服务的动作。要求,如果服务调用一次失败,则在应用程序中继续进行错误状态之前,我必须尝试仅再次调用一次服务。我为此使用了promise-retry模块,并且能够使其在本地工作。但是,我现在正在尝试为promiseRetry包裹的服务调用自己编写单元测试(Mocha),并且很难通过有意义的测试。首先,这是包装在promiseRetry中的调用服务的操作。

import promiseRetry from 'promise-retry';

...

const sendNotification = () => {
    return (dispatch, getState) => {
        const request = buildNotificationRequest(getState);

        dispatch(createNotificationAttempt());

        promiseRetry((retry) => {
            return createNotificationService(request)
                .catch(retry);
            }, {retries: 1}).then(
                () => {
                    dispatch(createNotificationSuccess());
                },
                (error) => {
                    dispatch(createNotificationError(error));
                }
            );
        };
    };

通常,我为调用服务的操作编写单元测试的方式是这样的:

describe('notification actions', () => {
    beforeEach(() => {
        sendNotification = sinon.stub(services, 'createNotificationService').returns(Promise.resolve({}));
    });

    it('should log an attempt', () => {
        store.dispatch(notificationActions.sendNotification());
        const actions = store.getActions();
        expect(actions[0].type).to.equal(notificationActions.ACTION_TYPES.CREATE_NOTIFICATION_ATTEMPT);
    });
});

这对于测试初始尝试是很好的方法,但是由于某些原因,即使我可以调试并逐步完成测试,并击中promiseRetry内部的所有代码,以及其中的操作(例如dispatch(createNotificationSuccess()), ))没有登录到存储中,因此我无法在它们上运行Expect语句。到目前为止,我尝试过的每个角度都只能从商店中检索尝试,而我无法从Promise的成功或失败方面获取任何数据。

我已经在Stack Overflow上找到了一些有关测试promise-retry本身的信息,但是我需要知道,如果我对正在调用的服务存根并使其强制失败,它将记录下另一个尝试和另一个失败。或者,如果我对服务进行存根并强制其成功,则它将仅记录一次尝试,一次成功并完成。正如我前面提到的,即使单步调试显示所有这些代码行都被击中,我在存储区中获得的唯一动作就是尝试,而与成功或失败无关。

这是我无法通过的测试示例:

import * as services from 'services.js';

...

describe('the first time the service call fails', () => {
    const error = {status: 404};

    beforeEach(() => {
        sendNotification = sinon.stub(services, 'createNotificationService').returns(Promise.reject(error));
    });

    it('should log a retry', () => {
        store.dispatch(notificationActions.sendNotification());
        const actions = store.getActions();
        expect(actions[0].type).to.equal(notificationActions.ACTION_TYPES.CREATE_NOTIFICATION_ATTEMPT); // this passes
        expect(actions[1].type).to.equal(notificationActions.ACTION_TYPES.CREATE_NOTIFICATION_FAILURE); // this fails because there are no other actions logged in the store.

也许我误解了诺言重试的工作方式?它不是应该在第一次失败时击中我的错误操作(dispatch(createNotificationError(error)),而第二次(如果适用)是否击中我的错误操作;否则,应该至少记录两次尝试。有什么建议吗?

0 个答案:

没有答案