【问题标题】:How can I test Thunk actions with Jest?如何使用 Jest 测试 Thunk 操作?
【发布时间】:2017-12-18 07:12:45
【问题描述】:

我是使用 Jest 对 Redux-Thunk 异步操作进行单元测试的新手。

这是我的代码:

export const functionA = (a, b) => (dispatch) => {
    dispatch({ type: CONSTANT_A, payload: a });
    dispatch({ type: CONSTANT_B, payload: b });
} 

如何使用 Jest 测试此功能?

【问题讨论】:

    标签: unit-testing redux jestjs redux-thunk


    【解决方案1】:

    Redux 文档中有一个示例:http://redux.js.org/docs/recipes/WritingTests.html#async-action-creators

    import configureMockStore from 'redux-mock-store'
    import thunk from 'redux-thunk'
    const middlewares = [thunk]
    const mockStore = configureMockStore(middleware)
    
    describe('async actions', () => {
        
      it('should dispatch actions of ConstantA and ConstantB', () => {
        const expectedActions = [
          {type: CONSTANT_A, payload: 'a'},
          {type: CONSTANT_B, payload: 'b'} 
        ]
    
        const store = mockStore({ yourInitialState })
        store.dispatch(actions.functionA('a', 'b'))
    
        expect(store.getActions()).toEqual(expectedActions)
      })
    })
    

    【讨论】:

    • 感谢@luanped 的回答,我试过了,但没用。问题是,我的功能不是 Promise :(
    • 那就更简单了,我用一个例子更新了答案
    • 好方法,说教!
    【解决方案2】:

    我建议你写这样的东西来避免异步问题:

    return store
      .dispatch(actionCreators.login({}))
      .then(() => expect(store.getActions()).toEqual(expectedActions));
    

    【讨论】:

      【解决方案3】:

      另外,为了更方便,你可以使用这个模块:https://www.npmjs.com/package/redux-thunk-tester

      例子:

      import React from 'react';
      import {createStore, applyMiddleware, combineReducers} from 'redux';
      import {reducer} from './example';
      import ReduxThunkTester from 'redux-thunk-tester';
      import thunk from 'redux-thunk';
      
      const request = (ms) => new Promise((resolve) => {
        setTimeout(() => resolve('success response'), ms);
      });
      
      const resultRequestAction = (value) => ({ type: SOME_BACKEND_REQUEST, payload: value });
      const toggleLoadingAction = (value) => ({ type: TOGGLE_LOADING, payload: value });
      
      const asyncThunkWithRequest = () => async (dispatch) => {
        try {
          dispatch(toggleLoadingAction(true));
          const result = await request(200);
          dispatch(resultRequestAction(result));
        } finally {
          dispatch(toggleLoadingAction(false));
        }
      };
      
      const createMockStore = () => {
        const reduxThunkTester = new ReduxThunkTester();
      
        const store = createStore(
          combineReducers({exampleSimple: reducer}),
          applyMiddleware(
            reduxThunkTester.createReduxThunkHistoryMiddleware(),
            thunk
          ),
        );
      
        return {reduxThunkTester, store};
      };
      
      describe('Simple example.', () => {
        test('Success request.', async () => {
          const {store, reduxThunkTester: {getActionHistoryAsync, getActionHistoryStringifyAsync}} = createMockStore();
      
          store.dispatch(asyncThunkWithRequest());
      
          const actionHistory = await getActionHistoryAsync(); // need to wait async thunk (all inner dispatch)
      
          expect(actionHistory).toEqual([
            {type: 'TOGGLE_LOADING', payload: true},
            {type: 'SOME_BACKEND_REQUEST', payload: 'success response'},
            {type: 'TOGGLE_LOADING', payload: false},
          ]);
      
          expect(store.getState().exampleSimple).toEqual({
            loading: false,
            result: 'success response'
          });
      
          console.log(await getActionHistoryStringifyAsync({withColor: true}));
        });
      });
      
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-09-14
        • 2018-06-18
        • 2017-03-03
        • 2020-09-24
        • 2017-05-28
        • 2017-06-18
        • 2017-10-19
        • 1970-01-01
        相关资源
        最近更新 更多