Node.js 18中如何Mock fetch HTTP请求与响应?
Node.js 18中Mock fetch API的几种方案
我正在使用Node.js 18新增的fetch API发送HTTP请求,示例代码如下:
const response = await fetch(SOMEURL) const json = await response.json()
这段代码能正常运行,但我需要Mock这些HTTP请求来做自动化测试,通过模拟响应验证代码逻辑。之前用Axios时搭配nock包Mock请求,但nock和Node.js 18的fetch不兼容,想知道怎么处理Node.js中fetch的Mock问题。
方案1:直接替换全局fetch
Node.js的fetch挂载在globalThis上,测试时可直接替换为自定义函数,实现基础Mock:
// 测试文件顶部覆盖全局fetch globalThis.fetch = async () => { return { json: async () => ({ data: 'mock response' }), // 按需添加response的其他属性/方法,比如status、text()等 status: 200 } } // 后续执行业务代码测试即可
如果需要根据不同URL返回差异化响应,可增加判断逻辑:
globalThis.fetch = async (url) => { if (url === 'https://api.example.com/data') { return { status: 200, json: async () => ({ id: 1, name: 'Mock Data' }) } } else { return { status: 404, json: async () => ({ error: 'Not Found' }) } } }
方案2:使用专门的Mock库
针对fetch的Mock需求,有几个成熟库可以简化操作:
jest-fetch-mock(适配Jest测试框架):
安装后在测试文件中启用并配置Mock:import fetchMock from 'jest-fetch-mock' // 启用Mock fetchMock.enableMocks() test('验证fetch请求与响应', async () => { // 模拟单次响应 fetchMock.mockResponseOnce(JSON.stringify({ data: 'mock content' }), { status: 200 }) const response = await fetch('https://api.example.com') const json = await response.json() expect(json).toEqual({ data: 'mock content' }) expect(fetchMock).toHaveBeenCalledWith('https://api.example.com') })msw(Mock Service Worker):
支持浏览器和Node.js环境,通过拦截网络请求实现Mock,适合复杂场景:import { setupServer } from 'msw/node' import { rest } from 'msw' // 创建Mock请求处理器 const server = setupServer( rest.get('https://api.example.com/data', (req, res, ctx) => { return res(ctx.status(200), ctx.json({ id: 1, name: 'Mocked Data' })) }) ) // 测试生命周期钩子 beforeAll(() => server.listen()) afterEach(() => server.resetHandlers()) afterAll(() => server.close()) // 测试代码 test('fetch接口数据', async () => { const response = await fetch('https://api.example.com/data') const json = await response.json() expect(json.name).toBe('Mocked Data') })
方案3:基于undici实现Mock
Node.js 18的fetch基于undici库实现,可直接利用undici的Mock能力:
import { MockAgent, setGlobalDispatcher } from 'undici' const mockAgent = new MockAgent() // 设置全局请求调度器为MockAgent setGlobalDispatcher(mockAgent) // 针对目标域名创建Mock连接池 const mockPool = mockAgent.get('https://api.example.com') // 拦截指定路径的请求并返回Mock响应 mockPool.intercept({ path: '/data' }) .reply(200, { data: 'mock from undici' }) // 测试代码 const response = await fetch('https://api.example.com/data') const json = await response.json() console.log(json) // { data: 'mock from undici' }
内容的提问来源于stack exchange,提问作者Glynn Bird
相关产品推荐
相关产品推荐

