TypeScript类方法内部的fetch如何mock实现单元测试
问题解决方案
问题根因
- 原测试代码错误覆盖了
postEvent方法,导致原方法内部逻辑完全不执行,自然不会调用到mock的fetch - fetch引用不匹配:业务代码使用全局
fetch,但测试中mock的是node-fetch模块,两者不属于同一个引用,mock不生效 - 直接修改导入的
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
相关产品推荐
相关产品推荐

