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

使用Jest Mock模拟Redux-Thunk函数时触发‘Actions must be plain objects’错误

解决Jest测试Redux-Thunk时的"Actions must be plain objects"错误

你遇到的这个报错本质是测试环境里的dispatch没有Redux-Thunk中间件的支持。看你的代码,functionToMock是一个Redux-Thunk风格的异步action creator(返回函数的函数),而functionToTest里直接把这个函数传给了dispatch——在真实的Redux环境中,Thunk中间件会自动执行这个函数,但你测试时用的mockdispatch只是个普通的jest函数,它只会接收plain object类型的action,自然会报错。

下面给你三个不同场景下的解决方案,你可以根据测试需求选择:

方案1:手动实现支持Thunk的Mock Dispatch

如果不想引入额外依赖,你可以自己写一个能处理Thunk的mock dispatch函数,它会自动判断传入的是函数还是普通action:

// 模拟一个支持Thunk的dispatch
const mockDispatch = jest.fn((action) => {
  // 如果传入的是Thunk函数,就调用它并传入自身
  if (typeof action === 'function') {
    return action(mockDispatch);
  }
  // 普通action直接返回
  return action;
});

然后在测试中使用这个mockDispatch代替普通的jest.fn():

import { functionToTest } from './your-actions-file';

test('functionToTest executes correctly', async () => {
  await functionToTest()(mockDispatch);
  
  // 验证底层的basic action被分发了
  expect(mockDispatch).toHaveBeenCalledWith({ type: 'a basic action' });
});

方案2:Mock functionToMock以隔离测试

如果你测试functionToTest的目标只是验证它调用了functionToMock,而不需要关心functionToMock内部的逻辑,可以直接mock这个函数,让它返回一个普通action或者resolved的Promise:

import * as actions from './your-actions-file';

// 保留其他action的真实实现,只mock functionToMock
jest.mock('./your-actions-file', () => ({
  ...jest.requireActual('./your-actions-file'),
  functionToMock: jest.fn(() => Promise.resolve({ type: 'MOCKED_ACTION' }))
}));

test('functionToTest calls functionToMock', async () => {
  const mockDispatch = jest.fn();
  await actions.functionToTest()(mockDispatch);
  
  // 验证functionToMock被调用
  expect(actions.functionToMock).toHaveBeenCalled();
  // 验证dispatch接收了mock的action
  expect(mockDispatch).toHaveBeenCalledWith({ type: 'MOCKED_ACTION' });
});

方案3:使用redux-mock-store配合Thunk中间件

如果要测试完整的action分发流程(包括多个action的顺序和内容),推荐用redux-mock-store这个库,它可以直接集成Thunk中间件:

首先安装依赖(如果还没装):

npm install redux-mock-store redux-thunk --save-dev

然后编写测试:

import configureMockStore from 'redux-mock-store';
import thunk from 'redux-thunk';
import * as actions from './your-actions-file';

// 创建带Thunk中间件的mock store
const middlewares = [thunk];
const mockStore = configureMockStore(middlewares);

test('functionToTest dispatches all expected actions', async () => {
  const store = mockStore({});
  
  // 分发functionToTest
  await store.dispatch(actions.functionToTest());
  
  // 获取所有被分发的action列表
  const dispatchedActions = store.getActions();
  
  // 验证basic action在列表中
  expect(dispatchedActions).toContainEqual({ type: 'a basic action' });
  // 还可以验证其他action的顺序和内容
});

总结

  • 如果你需要测试完整的Thunk执行流程:选方案1或3
  • 如果你只需要隔离测试functionToTest的调用逻辑:选方案2

内容的提问来源于stack exchange,提问作者Kevin

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 07:15:13