Как протестировать генератор асинхронных действий, который вызывает другое действие с помощью setTimeout

У меня есть следующее действие, которое отображает уведомление, а затем удаляет его, и я пытаюсь написать для него модульный тест, но я не могу понять, как издеваться над 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
    });

Следуя руководству на веб-сайте 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)
                });
        });
    });

прямо сейчас он просто выдает ошибку Невозможно прочитать свойство 'then' неопределенного в store.dispatch, любая помощь будет принята с благодарностью.


person Alexis Mondragon    schedule 02.03.2017    source источник
comment
Вы используете шутку?   -  person Prakash Sharma    schedule 02.03.2017


Ответы (1)


Прежде всего, поскольку ваш создатель действия ничего не возвращает, когда вы вызываете store.dispatch(actions.addNotification()), он возвращает undefined, и поэтому вы получаете ошибку 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);

Другой вариант — использовать стратегию, описанную в документации Jest.

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

При использовании этой стратегии Jest будет ждать вызова done(), в противном случае он будет считать тест завершенным при завершении выполнения тела теста.

person Lucas    schedule 02.03.2017