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

如何用Jest和React测试库模拟带自定义参数的axios Promise拒绝

问题根因

核心是模拟的axios拒绝值和业务代码实际运行时接收到的错误结构不一致,常见触发catch块error为undefined的原因有两个:

  1. 业务代码配置了axios响应拦截器处理错误格式,但jest模拟的axios未加载该拦截器逻辑,导致模拟值和实际运行时的错误格式不匹配
  2. 直接把响应对象作为拒绝值抛出,但真实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的对象即可

调试技巧

如果修改后仍然不生效,可以通过日志确认值的传递:

  1. 在测试代码中打印mock调用结果,确认返回值符合预期:console.log(mockedAxios.post.mock.results)
  2. 调整findByText的超时时间,避免异步操作未完成就触发断言:await screen.findByText(/404 blah/i, { timeout: 3000 })

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 01:45:03