通用
const originFetch = global.fetch; global.fetch = jest.fn((url, ops) => { if (url === 'https://static.figma.com/font/Inter_1') { return Promise.resolve({ arrayBuffer: () => Promise.resolve(new ArrayBuffer(0)), }); } return originFetch(url, ops); })
这段代码的作用是通过使用
jest.fn
来 mock(模拟)全局的 fetch
函数,方便在单元测试中控制 fetch
行为。具体来说:const originFetch = global.fetch;
:- 保存原始的全局
fetch
函数引用,以便在模拟fetch
后仍然可以调用原始的fetch
。
global.fetch = jest.fn((url, ops) => {...})
:- 使用
jest.fn
创建一个模拟函数,并将其赋值给全局fetch
,这样每当在测试中调用fetch
时,都会调用这个模拟函数,而不是原来的fetch
。
if (url === 'https://static.figma.com/font/Inter_1') {...}
:- 当请求的
url
是'https://static.figma.com/font/Inter_1'
时,返回一个模拟的Promise
,该Promise
的arrayBuffer
方法返回一个空的ArrayBuffer
对象。这样就可以模拟成功请求到该 URL 的场景。
return originFetch(url, ops);
:- 如果请求的
url
不是'https://static.figma.com/font/Inter_1'
,则调用原始的fetch
函数,保持其他请求的正常行为。
作用
- 这段代码通常用于测试环境下,模拟某些特定 URL 请求的响应结果(如返回一个空的
ArrayBuffer
),以控制测试的结果和行为。
- 这种方法允许你在不依赖实际网络请求的情况下测试基于
fetch
的代码逻辑。
示例:
当测试代码中有涉及到
fetch
请求 https://static.figma.com/font/Inter_1
时,测试会返回一个空的 ArrayBuffer
而不会实际发出请求,但其他 URL 的请求会继续使用真实的 fetch
。其他方式
除了使用
jest.fn
直接模拟 fetch
以外,还有几种常见的方式可以在测试中拦截和控制 fetch
的行为。以下是几种替代方案:1. 使用 jest.spyOn
监视 fetch
jest.spyOn
允许你监视某个对象上的方法,并可以选择返回自定义的结果,而不完全替换它。这种方式和 jest.fn
类似,但更加灵活。const fetchSpy = jest.spyOn(global, 'fetch').mockImplementation((url, ops) => { if (url === 'https://static.figma.com/font/Inter_1') { return Promise.resolve({ arrayBuffer: () => Promise.resolve(new ArrayBuffer(0)), }); } return originFetch(url, ops); });
- 优点: 可以保留对
fetch
的原始引用,只针对特定调用进行拦截。
2. 使用 msw
(Mock Service Worker)
msw
是一种更强大的方式,它不仅可以拦截 fetch
,还可以模拟完整的 HTTP 响应,适用于更复杂的测试场景。你可以在测试中使用它来控制网络请求的行为。安装
msw
:npm install msw --save-dev
使用方式:
import { rest } from 'msw'; import { setupServer } from 'msw/node'; // 设置 mock 服务器 const server = setupServer( rest.get('https://static.figma.com/font/Inter_1', (req, res, ctx) => { return res(ctx.arrayBuffer(new ArrayBuffer(0))); }) ); // 在测试开始前启动服务器 beforeAll(() => server.listen()); // 在每个测试后重置服务器 afterEach(() => server.resetHandlers()); // 在所有测试结束后关闭服务器 afterAll(() => server.close());
- 优点:
msw
允许你模拟整个网络层,并且支持更复杂的响应场景(如状态码、响应头、延迟等)。它的使用体验更接近真实的 HTTP 流程。
3. 使用 fetch-mock
fetch-mock
是一个专门用来拦截和模拟 fetch
请求的库。它可以方便地设置请求匹配模式、响应类型等。安装
fetch-mock
:npm install fetch-mock --save-dev
使用方式:
import fetchMock from 'fetch-mock'; fetchMock.mock('https://static.figma.com/font/Inter_1', { arrayBuffer: () => Promise.resolve(new ArrayBuffer(0)), }); // 在测试结束后清除 mock afterEach(() => fetchMock.restore());
- 优点:
fetch-mock
提供了针对fetch
的全面模拟功能,支持灵活的请求匹配、序列化请求、批量处理等。
4. 直接修改 global.fetch
(不使用 jest.fn
)
你可以直接覆盖
global.fetch
,不使用 jest.fn
,这种方式适合于更简单的模拟需求。const originFetch = global.fetch; global.fetch = (url, ops) => { if (url === 'https://static.figma.com/font/Inter_1') { return Promise.resolve({ arrayBuffer: () => Promise.resolve(new ArrayBuffer(0)), }); } return originFetch(url, ops); }; // 在测试结束后恢复原始 fetch afterEach(() => { global.fetch = originFetch; });
- 优点: 直接覆盖的方式简单且有效,对于非常简单的测试场景来说是最轻量的解决方案。
总结
jest.fn
和jest.spyOn
都是 Jest 原生的 mock 方法,简单易用,适合基本的fetch
拦截。
msw
提供了更加真实的 HTTP 请求模拟,非常适合测试网络交互较多的应用。
fetch-mock
是一个专门的库,功能丰富,适合需要大量fetch
模拟的项目。
- 直接覆盖
global.fetch
是最轻量级的方式,适合简单测试场景。
你可以根据测试需求选择合适的方式来模拟
fetch
请求。