如何用Jest和React测试库模拟带自定义参数的axios Promise拒绝
问题根因
核心是模拟的axios拒绝值和业务代码实际运行时接收到的错误结构不一致,常见触发catch块error为undefined的原因有两个:
- 业务代码配置了axios响应拦截器处理错误格式,但jest模拟的axios未加载该拦截器逻辑,导致模拟值和实际运行时的错误格式不匹配
- 直接把响应对象作为拒绝值抛出,但真实axios抛出的错误是封装后的
AxiosError实例,响应数据默认挂载在error.response属性下
解决方案
方案1:匹配原始AxiosError结构(无自定义响应拦截器的场景)
如果业务代码没有配置拦截器转换错误,直接捕获原始axios错误,修改mock代码如下:
test('return throws error', async () => { // 模拟真实AxiosError结构,响应数据放在response字段下 mockedAxios.post.mockRejectedValue({ isAxiosError: true, response: { status: 404, statusText: 'blah' } }); userEvent.type(screen.getByLabelText(/username/i), 'blah'); userEvent.type(screen.getByLabelText(/password/i), 'blah'); userEvent.click(screen.getByRole('button')); const error = await screen.findByText(/404 blah/i); expect(error).toBeInTheDocument(); });
同时调整catch块的取值逻辑,从response字段下取属性:
} catch (error) { let errMessage = 'Service Error'; // 确认isErrorResp逻辑会校验isAxiosError以及response字段存在 if (isErrorResp(error)) { errMessage = `${error.response.status} ${error.response.statusText}`; } setNetworklError({ error: true, message: errMessage }); setIsloading(false); }
方案2:匹配自定义拦截器处理后的错误结构(有拦截器的场景)
如果业务代码的axios响应拦截器中已经做了错误转换,类似如下逻辑:
axios.interceptors.response.use( res => res.data, err => Promise.reject(err.response || new Error('Service Error')) )
jest模拟的axios默认不会加载业务代码中注册的拦截器,可二选一处理:
- 保持现有mockRejectedValue写法不变,在测试初始化时手动注册业务代码中的axios拦截器,确保测试环境和生产环境的错误处理逻辑一致
- 不加载拦截器的情况下,直接模拟拦截器输出的结果,调整mockRejectedValue的参数为拦截器最终reject的对象即可
调试技巧
如果修改后仍然不生效,可以通过日志确认值的传递:
- 在测试代码中打印mock调用结果,确认返回值符合预期:
console.log(mockedAxios.post.mock.results) - 调整
findByText的超时时间,避免异步操作未完成就触发断言:await screen.findByText(/404 blah/i, { timeout: 3000 })
内容的提问来源于stack exchange,提问作者Redeyes10
相关产品推荐
相关产品推荐

