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

TypeScript类方法内部的fetch如何mock实现单元测试

问题解决方案

问题根因

  1. 原测试代码错误覆盖了postEvent方法,导致原方法内部逻辑完全不执行,自然不会调用到mock的fetch
  2. fetch引用不匹配:业务代码使用全局fetch,但测试中mock的是node-fetch模块,两者不属于同一个引用,mock不生效
  3. 直接修改导入的fetch变量赋值无效,ES模块导入的绑定是只读的,无法直接覆盖

修复方案

方案1:使用spyOn mock全局fetch(推荐)

类型报错的核心是你mock的返回值不符合TS内置Response类型定义,用as unknown as Response做类型断言即可绕开校验,不需要补全所有非必要属性。
完整可运行测试代码如下:

import { MyClass } from './my-class';

describe('My class mocked fetch', () => {
  let fetchMock: jest.SpyInstance;
  let myClass: MyClass;

  beforeEach(() => {
    // 实例化被测类
    myClass = new MyClass();
    // mock全局fetch,加类型断言解决类型报错
    fetchMock = jest.spyOn(global, 'fetch').mockResolvedValue({
      url: 'url',
      status: 200,
      statusText: 'OK',
      ok: true,
      // 用到的Response方法可以按需mock
      json: jest.fn().mockResolvedValue({}),
      text: jest.fn().mockResolvedValue('')
    } as unknown as Response);
  });

  // 测试结束恢复原生fetch,避免污染其他用例
  afterEach(() => {
    fetchMock.mockRestore();
  });

  it('Calls mockedFetch and gets the mocked values', async () => {
    expect(fetchMock).toHaveBeenCalledTimes(0);
    // 传参符合eventSchema类型即可,测试场景可以用as any绕开校验
    const response = await myClass.postEvent({} as any);
    console.log('RESPONSE', response);
    // 可选断言:验证fetch调用参数是否符合预期
    expect(fetchMock).toHaveBeenCalledTimes(1);
    expect(fetchMock).toHaveBeenCalledWith('url', expect.objectContaining({
      method: 'POST',
      headers: expect.objectContaining({
        'Content-type': 'application/json',
        'Api-Key': 'APIKEY}'
      })
    }));
    // 验证返回值为mock内容
    expect(response.status).toBe(200);
  });
});

方案2:业务代码明确导入node-fetch时的修复

如果你的业务代码顶部有import fetch from 'node-fetch'声明,用以下方式mock即可:

import { MyClass } from './my-class';
import fetch from 'node-fetch';

jest.mock('node-fetch');
const mockFetch = fetch as jest.MockedFunction<typeof fetch>;

describe('My class mocked fetch', () => {
  let myClass: MyClass;
  beforeEach(() => {
    myClass = new MyClass();
    mockFetch.mockResolvedValue({
      url: 'url',
      status: 200,
      statusText: 'OK',
      ok: true,
      json: jest.fn().mockResolvedValue({})
    } as unknown as Response);
  });

  afterEach(() => {
    mockFetch.mockReset();
  });

  // 测试用例和方案1一致
});

额外优化点

业务代码中result = await response属于冗余逻辑,response已经是await fetch返回的Response实例,不需要二次await,直接return response即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 11:39:00