使用Jest测试createAsyncThunk时出现匹配器报错的原因排查
测试逻辑问题核心原因
- 断言对象不满足匹配器的类型要求
createAsyncThunk生成的action创建器,传入参数执行后会返回一个带固定结构的特殊Promise对象,也就是你报错中看到的挂载了abort、arg、requestId属性的对象,它本身不是jest可识别的mock/spy函数。而你使用的toHaveBeenCalledWith匹配器,强制要求传入的接收值必须是被模拟过的函数,直接用这个对象做断言,必然触发类型不匹配的报错。 - 验证路径错位
你想验证myFunc接收到了正确入参,但没有对应到正确的字段:这个特殊Promise对象上的arg属性,本身就存储了调用thunk时传入的全部参数,完全不需要通过函数类的调用匹配器做验证。 - 缺少异步等待流程
thunk内部包含await axios.post的异步逻辑,当前测试代码没有await等待异步执行完成,就算没有类型报错,拿到的也只是未完成的Promise状态,无法获取真实执行结果。 - 未模拟外部依赖
测试没有对axios做模拟,会在单元测试环境下触发真实网络请求,大概率会出现请求超时、跨域报错等额外问题。
修正后的测试参考
首先全局模拟axios模块替换真实请求逻辑,再调整断言逻辑:
// 全局mock axios,替换真实网络请求 jest.mock('axios'); test('returns ID when myFunc is called', async () => { const nameAndEmail = { name: 'John Smith', email: '123@123.com' }; // 模拟后端接口的固定返回值 axios.post.mockResolvedValue({ data: { id: 123 } }); // 等待thunk异步流程完全执行完成 const thunkExecutionResult = await store.dispatch(myFunc(nameAndEmail)); // 验证thunk携带的入参正确 expect(thunkExecutionResult.arg).toEqual(nameAndEmail); // 验证后端接口调用的路径、参数完全匹配 expect(axios.post).toHaveBeenCalledWith('/backendroute', nameAndEmail); // 验证thunk最终返回的用户ID符合预期 expect(thunkExecutionResult.payload).toBe(123); });
注意事项
- 基于
configureStore搭建的测试store,dispatch执行asyncThunk后返回的结果对象,会自动把thunk的最终返回值挂载在payload字段,不需要额外手动处理。 - 不需要对thunk本身做spy,只要mock透传的外部HTTP依赖,就能完整覆盖thunk的全链路逻辑。
- 你当前写的thunk基础实现存在语法缺失:
createAsyncThunk接收两个参数,你传入第二个async回调后缺少收尾的右括号,正常写法需要在回调结束后补全),否则运行时会直接触发语法报错。
内容的提问来源于stack exchange,提问作者ffx292
相关产品推荐
相关产品推荐

