【问题标题】:how to test a redux action that dispatch other action如何测试调度其他操作的 redux 操作
【发布时间】:2021-11-25 17:56:35
【问题描述】:

我正在使用 jest + react 测试库

正如标题所描述的,我要测试的是 testAction 调度了 secondTestAction,但是我收到一个错误,说 secondTestAction 没有调度,这不可能是真的,因为正在打印函数上的消息。

任何人都知道我怎样才能使这个测试工作?

动作

export const testAction = () => async (dispatch) => {
    dispatch(secondTestAction());
};
export const secondTestAction = () => {
    console.log('second action have been dispatched');
};

测试

import '@testing-library/jest-dom/extend-expect';
import * as userActions from '../../../redux/actions/userActions';
import store from '../../../redux/store';

const secondTestActionSpy = jest.spyOn(userActions, 'secondTestAction');

test('should dispatch secondTestActions ', async () => {
    await store.dispatch(userActions.testAction());
    expect(secondTestActionSpy.mock.calls.length).toBe(1);
});

错误

expect(received).toBe(expected) // Object.is equality
Expected: 1
Received: 0
expect(secondTestActionSpy.mock.calls.length).toBe(1);

【问题讨论】:

    标签: reactjs redux react-redux jestjs react-testing-library


    【解决方案1】:

    您看,您正在将所有操作(那些是export'ed)导入测试。然后你在本地 - 仅在测试中 - 用间谍包装器替换导入的操作之一。但是userActions.js 中的操作不会转到您的测试文件,一个函数只是直接调用另一个函数,只是声明的那个版本,而不是一个带有间谍包的版本。

    你能做什么?如果您想遵循“测试该操作已被调用”的方法,您可以使用redux-mock-store:

    import { testAction, secondAction } from '../../../redux/actions/userActions';
    
    test('should dispatch secondTestActions ', async () => {
        mockedStore.dispatch(userActions.testAction());
        expect(mockedStore.getActions()).toContainEqual(secondAction());
    });
    
    

    那么如何制作这个mockedStore?只需使用来自redux-mock-store 的默认导出:

    import configureMockStore from 'redux-mock-store';
    import thunk from 'redux-thunk';
    
    const middlewares = [thunk];
    const mockStore = configureMockStore(middlewares)(constantStoreData);
    

    由于redux-mock-store 不通过reducer 处理动作,它实际上并不要求你依赖reducer。所以这里不需要../store。

    但是这样你只需要测试调用了什么动作(以及以什么顺序 - 如果你使用expect(store.getActions()).toEqual(...而不是expect(store.getActions()).toContainEqual(...)。

    在我看来,作为一个整体测试 store 更容易、更可靠 - 使用 action 和 reducer,仅模拟外部交互(如对服务器的请求、使用 localstorage 的操作等)。然后测试会派发一些动作并确保最终状态符合预期:

    it('sets loading once request started', () => {
      const realStore = createStore(userReducer, someInitialState);
      realStore.dispatch(loadUsersAction(someArgument));
      expect(realStore.getState().isLoading).toEqual(true);
    });
    
    it('unsets loading once loading users failed', async () => {
      // mock specific request to fail
      const realStore = createStore(userReducer, someInitialState);
      realStore.dispatch(loadUsersAction(someArgument));
      await undefined; // let's skip Promises queue once; does nothing special, await 42 would work the same;
      expect(realStore.getState().isLoading).toEqual(false);
    });
    

    【讨论】:

      猜你喜欢
      • 2017-05-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-05-07
      • 1970-01-01
      • 2016-08-17
      • 2016-02-21
      • 2018-04-26
      相关资源
      最近更新 更多