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

React组件fetch中AbortController测试本应通过却失败问题

React组件AbortController请求逻辑测试失败修复方案

问题根因

  • 组件代码存在变量拼写错误:定义的中断控制器实例名为abortController,传入fetch的signal配置时错写为ammAbortController.signal,未定义变量会直接触发引用错误。
  • 测试等待逻辑不完整:renderComponent仅等待了组件渲染的act周期,没有等待fetch请求的Promise链(含catch分支)完全执行,jest-circus会提前检测到未被即时处理的Promise拒绝,直接抛出你看到的thrown: Object {name: "AbortError"}报错。
  • mock的AbortError不符合真实实现:直接reject普通对象和浏览器真实抛出的AbortError(DOMException实例)存在差异,可能导致分支判断失效。

修复方案

1. 修正组件代码拼写错误

将useEffect中fetch调用的signal参数改为正确的变量引用,同步修复同一段代码里的参数覆盖、构造函数传参错误:

useEffect(() => {
  const abortController = new AbortController();
  const url = 'string'
  // 修正错误的变量名引用
  fetch(url, {signal: abortController.signal})
    .then(res => res.json())
    .then((data) => {
      if (!data || !data.result || !Array.isArray(data.result)) {
        setData([]);
        return;
      }
      // 修正参数名覆盖、传入错误构造参数的问题
      const newData = data.result.map(item => new Data(item));
      setData(newData);
    })
    .catch(err => {
      // 兼容不同运行时的AbortError判断
      if (err.name === "AbortError" || err.code === DOMException.ABORT_ERR){return}
      console.error(err);
    });
  return ()=>abortController.abort();
  // eslint-disable-next-line react-hooks/exhaustive-deps
}, [trigger]);

2. 完善测试用例的等待与mock逻辑

补全微任务等待逻辑,使用更贴近真实场景的AbortError mock,测试结束后恢复mock避免污染其他用例:

import { act, render, waitFor } from '@testing-library/react';
import { BrowserRouter } from 'react-router-dom';

const renderComponent = async () => {
  await act(async() => {
    component = await render(
      <BrowserRouter>
        <Component runningTest={true}/>
      </BrowserRouter>
    );
  })
};

it.only('fetch触发AbortError时不会打印控制台错误', async () => {
  const errorSpy = jest.spyOn(console, 'error').mockImplementation(()=>{});
  // 模拟真实场景下的AbortError,使用标准DOMException构造
  global.fetch = jest.fn(() => {
    return Promise.reject(new DOMException('Aborted', 'AbortError'));
  });

  await renderComponent();
  // 等待所有Promise微任务执行完成,确保catch分支逻辑跑完
  await waitFor(() => {
    expect(errorSpy).toHaveBeenCalledTimes(0);
  });

  // 恢复mock,避免影响其他测试用例
  errorSpy.mockRestore();
  global.fetch.mockRestore();
});

验证说明

修复后测试会等待fetch的catch分支完整执行,AbortError会被正确捕获并跳过console.error调用,断言可以正常通过,不会再出现jest-circus抛出未处理reject的报错。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.03 00:42:30