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

如何修复useEffect中使用axios CancelToken时的测试失败问题

没错,mock axios.CancelToken.source() 确实能解决这个测试失败的问题,咱们先理清楚问题出在哪:当测试用例执行完毕,RTL会卸载组件,触发useEffect的清理函数调用source.cancel()——这个操作会尝试取消MSW正在处理的请求,可能导致Promise被reject,哪怕你的catch分支判断了axios.isCancel(error),但MSW对取消请求的处理可能会抛出未被捕获的错误,最终导致测试失败。

下面是具体的实现方案:

方案一:全局mock axios的CancelToken

在测试文件的顶部添加全局mock,保留axios其他原有功能,只替换CancelToken相关逻辑:

jest.mock('axios', () => ({
  ...jest.requireActual('axios'), // 保留axios原有的其他方法和属性
  CancelToken: {
    source: jest.fn(() => ({
      token: {}, // 只需提供一个组件能正常传入的token对象即可
      cancel: jest.fn() // 空实现的cancel方法,不会真的触发请求取消
    }))
  },
  isCancel: jest.fn(() => false) // 可选:mock isCancel方法,避免进入cancel错误分支
}));

方案二:单个测试用例内局部mock

如果你不想影响其他测试用例,可以在当前测试里临时mock,测试结束后恢复原方法:

it('should render title to page', () => {
  // 保存原方法引用
  const originalSource = axios.CancelToken.source;
  // 临时替换为mock函数
  axios.CancelToken.source = jest.fn(() => ({
    token: {},
    cancel: jest.fn()
  }));

  const { getByText } = render(<EditIndex />);
  const heading = getByText('Edit Items');
  expect(heading.textContent).toEqual('Edit Items');

  // 测试完毕恢复原方法
  axios.CancelToken.source = originalSource;
});

额外注意:检查MSW配置的小问题

你提供的MSW服务器代码里有个笔误——rest.get('/api/data/'), 后面多了个逗号,正确的写法应该是:

const server = setupServer(
  rest.get('/api/data/', (req, res, ctx) => {
    return res(
      ctx.status(200),
      ctx.json({ data: data })
    );
  })
);

这个小错误也可能导致请求处理异常,进而影响测试结果,建议先修正。

总的来说,mock CancelToken.source后,组件卸载时的cancel操作变成了空执行,不会干扰MSW的请求流程,测试就能正常通过了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.09 15:22:52