如何测试返回dispatch函数的Redux异步Action?
问题:测试Redux中返回dispatch函数的Action
场景说明
我正在开发一个用Redux做状态管理的React应用,流程是视图触发Action,进而修改Reducer的状态。已经成功完成了视图和Reducer的测试,但不知道怎么测试返回dispatch函数的Action文件,以下是相关代码和失败的测试示例。
相关代码
需要测试的Action文件
import {Dispatch} from 'redux' import {AuthAction, AuthActionTypes, SetUserAction} from "../actions-types/auth-actions-types"; export const setUserAction = (user: User) => { return async (dispatch: Dispatch<SetUserAction>) => { dispatch({ type: AuthActionTypes.SET_USER, payload: user }) } }
Reducer代码
import {AuthAction, AuthActionTypes} from "../actions-types/auth-actions-types"; export const initialAuthState = { auth: {}, user: null }; const reducer = (state = initialAuthState, action: AuthAction) => { switch(action.type) { case AuthActionTypes.SET_USER: return { ...state, user: action.payload, }; default: return state } } export default reducer
可正常运行的Reducer测试代码
import authReducer, {initialAuthState} from "./auth-reducer"; import {AuthActionTypes} from "../actions-types/auth-actions-types"; describe('Auth Reducer', ()=>{ test('should return user correctly ', ()=>{ const mockPayload = { name: 'any_name', emaiL: 'any_email', accessToken: 'any_tokem' } const newState = authReducer(initialAuthState, { type: AuthActionTypes.SET_USER, payload: mockPayload }) expect(newState.user).toEqual(mockPayload); }) })
存在问题的Action测试代码
describe('AuthAction', ()=>{ test('setUserAction', ()=>{ const user = { name: 'any_user', email: 'any_email', token: 'any_token' } const result = setUserAction(); expect(result).toEqual(user); }) })
测试失败信息:
Expected: {"email": "any_email", "name": "any_user", "token": "any_token"} Received: [Function anonymous]
问题分析
测试失败的核心原因:setUserAction是一个返回异步Thunk函数的Action创建器,并非直接返回user对象。你不仅漏传了user参数,还错误地将返回的Thunk函数和user对象做相等断言,自然会失败。
正确的测试方法
测试这类Redux Thunk Action,核心是验证dispatch是否被正确调用,且传入的Action类型、payload符合预期,以下是两种常用方案:
方案1:手动模拟dispatch函数
import { setUserAction } from './auth-actions'; import { AuthActionTypes } from '../actions-types/auth-actions-types'; describe('AuthAction', () => { test('setUserAction should dispatch correct SET_USER action', async () => { // 1. 创建模拟dispatch函数 const mockDispatch = jest.fn(); const mockUser = { name: 'any_user', email: 'any_email', token: 'any_token' }; // 2. 获取Thunk函数并传入模拟dispatch执行 const thunk = setUserAction(mockUser); await thunk(mockDispatch); // 3. 验证dispatch调用情况 expect(mockDispatch).toHaveBeenCalledTimes(1); expect(mockDispatch).toHaveBeenCalledWith({ type: AuthActionTypes.SET_USER, payload: mockUser }); }); });
方案2:使用redux-mock-store模拟Store
若有大量异步Action需要测试,可借助redux-mock-store简化流程:
首先安装依赖:
npm install redux-mock-store --save-dev
编写测试代码:
import configureMockStore from 'redux-mock-store'; import thunk from 'redux-thunk'; import { setUserAction } from './auth-actions'; import { AuthActionTypes } from '../actions-types/auth-actions-types'; // 创建带Thunk中间件的模拟Store const mockStore = configureMockStore([thunk]); describe('AuthAction', () => { test('setUserAction should dispatch SET_USER action', async () => { const mockUser = { name: 'any_user', email: 'any_email', token: 'any_token' }; const store = mockStore({}); // 执行Action await store.dispatch(setUserAction(mockUser)); // 获取所有已dispatch的Action const actions = store.getActions(); // 验证Action正确性 expect(actions[0]).toEqual({ type: AuthActionTypes.SET_USER, payload: mockUser }); }); });
关键注意事项
- 必须给
setUserAction传入user参数,否则Thunk函数无法生成正确的Action payload - 由于Action返回的是异步函数,测试时要加
async/await确保异步逻辑执行完成 - 测试重点是验证dispatch的调用行为,而非Action创建器的返回值
内容的提问来源于stack exchange,提问作者Tiago Palmas
相关产品推荐
相关产品推荐

