You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何测试返回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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 14:48:16