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

使用Jest模拟fetch请求时抛出TypeError: Cannot read properties of undefined (reading 'then')

解决Jest模拟fetch时的TypeError问题

错误原因分析

你遇到的TypeError: Cannot read properties of undefined (reading 'then'),本质是fetch调用后返回了undefined,导致无法调用.then()方法。这通常是因为global.fetch的模拟没有被正确挂载,或者测试执行时fetch并未指向你定义的mock函数。同时,即使mock正确,直接在render后断言也会因为异步操作未完成而无法获取更新后的DOM内容。

修复步骤

1. 正确模拟fetch(推荐使用jest.spyOn)

替换直接赋值global.fetch的方式,改用jest.spyOn来模拟,这样能更好地兼容TypeScript类型,同时确保mock被正确挂载:

import { render, waitFor } from "@testing-library/react";
import App from "./App";

describe("App", () => {
  beforeEach(() => {
    // 重置并模拟fetch
    jest.spyOn(global, 'fetch').mockResolvedValue({
      json: jest.fn().mockResolvedValue({ value: "This is a test joke" })
    } as Response);
  });

  afterEach(() => {
    // 清理mock,避免影响其他测试
    jest.restoreAllMocks();
  });

  it("loads the joke on mount", async () => {
    const { container } = render(<App />);
    
    // 等待异步操作完成,DOM更新
    await waitFor(() => {
      expect(container.innerHTML).toContain("This is a test joke");
    });
  });
});

2. 关键说明

  • 使用jest.spyOn替代直接赋值global.fetch:这种方式会保留原对象的类型,避免TypeScript类型断言带来的潜在问题,同时更容易在测试后清理。
  • 添加beforeEach和afterEach:确保每个测试前mock都是全新的,测试后恢复原fetch,防止测试间的副作用。
  • 使用waitFor:因为useEffect中的fetch是异步操作,render后DOM不会立即更新,waitFor会等待断言条件满足后再执行,避免因异步时序问题导致的断言失败。

3. 兼容TypeScript的直接赋值写法(备选)

如果你坚持直接赋值global.fetch,需要确保mock的结构完全符合fetch的类型定义:

global.fetch = jest.fn(() =>
  Promise.resolve({
    json: () => Promise.resolve({ value: "This is a test joke" }),
    ok: true // 添加必要的Response属性
  }) as Response
);

但这种方式不如jest.spyOn灵活,且容易留下测试污染,更推荐第一种方案。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 03:35:12