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

如何在Jest中测试React组件内链式调用的useEffect钩子

解决方案

你的测试思路没有问题,无法触发第二个useEffect的核心原因是你mock的XMLHttpRequest没有正确执行onload回调,导致setList状态更新逻辑没有运行,自然不会触发依赖list的第二个useEffect。
你可以按照以下步骤调整你的mock逻辑:

1. 完善XHR mock结构

需要确保你mock的XHR实例允许挂载onload回调,且预置好模拟的响应数据,示例如下(以Jest测试框架为例):

// 测试用例前置逻辑中完成XHR mock
const mockXHRInstance = {
  open: jest.fn(),
  send: jest.fn(),
  status: 200,
  response: JSON.stringify({
    list: [{ name: "选项A" }, { name: "选项B" }] // 你需要模拟的返回列表数据
  })
};
window.XMLHttpRequest = jest.fn(() => mockXHRInstance);

2. 主动触发onload回调

当你模拟input输入事件、触发第一个useEffect执行后,手动调用你挂载在mock XHR实例上的onload回调,模拟请求成功返回的场景:

// 第一步:模拟用户输入,触发第一个useEffect
const inputEl = screen.getByRole("textbox");
fireEvent.change(inputEl, { target: { value: "触发请求的输入值" } });

// 第二步:主动执行XHR的onload回调,触发内部setList逻辑
mockXHRInstance.onload({ target: mockXHRInstance } as ProgressEvent);

3. 等待状态更新落地后断言

因为React的状态更新和useEffect执行是异步批量处理的,建议用waitFor包裹后续的断言逻辑,确保第二个useEffect已经执行完成、select DOM已经更新:

await waitFor(() => {
  const optionEls = screen.getAllByRole("option");
  // 验证选项数量:1个默认占位选项 + 2个模拟返回的选项
  expect(optionEls).toHaveLength(3);
  expect(screen.getByText("选项A")).toBeInTheDocument();
});

额外排查点

如果调整后依然无法触发,可检查两个常见问题:

  • 你mock的XHR实例是否是每次new XMLHttpRequest时返回的同一个对象,确保onload回调是挂载到你能控制的实例上
  • 确认你模拟的响应status符合代码中>=200 && <400的判断条件,避免进入异常分支没有执行setList

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 00:27:03