如何测试使用setTimeout调用另一个动作的异步动作创建者

Ale*_*gon 5 javascript jestjs redux redux-thunk redux-mock-store

我有以下显示通知的操作,然后将其删除,我正在尝试为此编写一个单元测试,但似乎无法弄清楚如何模拟setTimeout。

export const addNotification = (text, notificationType = 'success', time = 4000) => {
        return (dispatch, getState) =>{
            let newId = new Date().getTime();
            dispatch({
                type: 'ADD_NOTIFICATION',
                notificationType,
                text,
                id: newId
            });
            setTimeout(()=>{
                dispatch(removeNotification(newId))
            }, time)
        }
    };
    export const removeNotification = (id) => (
    {
        type: 'REMOVE_NOTIFICATION',
        id
    });
Run Code Online (Sandbox Code Playgroud)

遵循redux网站上有关异步测试的教程,我提出了以下测试:

    import * as actions from '../../client/actions/notifyActionCreator'
    import configureMockStore from 'redux-mock-store'
    import thunk from 'redux-thunk'

    const middlewares = [ thunk ];
    const mockStore = configureMockStore(middlewares);


    describe('actions', ()=>{

        it('should create an action to add a notification and then remove it', ()=>{

            const store = mockStore({ notifications:[] });

            const text = 'test action';
            const notificationType = 'success';
            const time = 4000;
            const newId = new Date().getTime();

            const expectedActions = [{
                type: 'ADD_NOTIFICATION',
                notificationType,
                text,
                id: newId
            },{
                type: 'REMOVE_NOTIFICATION',
                id: newId
            }];

            return store.dispatch(actions.addNotification(text,notificationType,time))
                .then(() => {
                    expect(store.getActions()).toEqual(expectedActions)
                });
        });
    });
Run Code Online (Sandbox Code Playgroud)

现在,它仅引发错误无法在store.dispatch读取未定义的属性'then',将不胜感激。

Luc*_*cas 6

首先,由于您的动作创建者未返回任何内容,因此当您调用store.dispatch(actions.addNotification())它时会返回任何内容,这undefined就是您得到error的原因Cannot read property 'then' of undefined。使用.then()它应该返回一个承诺。

因此,您应该修复动作创建者或测试以反映动作创建者的实际行为。要使测试通过,您可以将测试更改为以下内容:

// set up jest's fake timers so you don't actually have to wait 4s
jest.useFakeTimers();

store.dispatch(actions.addNotification(text,notificationType,time));
jest.runAllTimers();
expect(store.getActions()).toEqual(expectedActions);
Run Code Online (Sandbox Code Playgroud)

另一种选择是使用Jest docs中详细介绍的策略。

// receive a function as argument
test('should create an action to add a notification and then remove it', (done)=>{

    // ...

    store.dispatch(actions.addNotification(text,notificationType,time));
    setTimeout(() => {
      expect(store.getActions()).toEqual(expectedActions);
      done();
    }, time);
});
Run Code Online (Sandbox Code Playgroud)

使用此策略时,Jest将等待done()被调用,否则它将在完成测试主体的执行时认为测试已结束。