msw是测试fetch异步请求的推荐方案,通过service worker拦截fetch和xmlhttprequest,返回预设响应,零侵入业务代码;也可用jest.mock(global.fetch)轻量模拟,但需注意await和node环境fetch polyfill。

测试 fetch 网络请求的异步结果,核心是**拦截真实 HTTP 请求、模拟响应,并验证代码对响应数据或错误的处理逻辑**。不依赖真实后端,也不让测试变慢或不稳定。
用 Mock Service Worker(MSW)拦截并模拟 fetch
MSW 是目前最推荐的方式,它在浏览器和 Node.js 中都能工作,通过拦截 `fetch`(和 `XMLHttpRequest`)来返回预设响应,且对业务代码零侵入。
- 安装:
npm install msw --save-dev - 创建 mock handlers(如
mocks/handlers.js):import { rest } from 'msw'; export const handlers = [ rest.get('https://api.example.com/users', (req, res, ctx) => { return res( ctx.status(200), ctx.json([{ id: 1, name: 'Alice' }, { id: 2, name: 'Bob' }]) ); }), rest.post('https://api.example.com/users', (req, res, ctx) => { return res(ctx.status(201), ctx.json({ id: 3, name: req.body.name })); }) ]; - 在测试中启动 MSW 并清理:
import { setupServer } from 'msw/node'; import { handlers } from './mocks/handlers'; const server = setupServer(...handlers); beforeAll(() => server.listen()); afterEach(() => server.resetHandlers()); afterAll(() => server.close()); test('fetches users and renders them', async () => { const users = await fetchUsers(); // 假设这是你封装的 fetch 函数 expect(users).toHaveLength(2); expect(users[0].name).toBe('Alice'); });
用 Jest 的 mock 实现轻量级 fetch 模拟
适合简单场景或快速验证逻辑,无需额外库。直接替换全局 fetch 为 jest.fn(),控制返回 Promise。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 在测试文件顶部 mock fetch:
global.fetch = jest.fn();
- 模拟成功响应:
fetch.mockResolvedValueOnce({ ok: true, json: async () => [{ id: 1, name: 'Alice' }] }); - 模拟网络错误或失败响应:
fetch.mockRejectedValueOnce(new Error('Network error')); // 或 fetch.mockResolvedValueOnce({ ok: false, status: 500, statusText: 'Internal Server Error' }); - 注意:需确保被测函数真正调用的是全局
fetch(未被封装成其他变量),否则 mock 不生效。
测试异步流程的关键点
fetch 返回 Promise,测试时必须 await 或返回 Promise,否则断言可能在异步操作完成前就执行。
- ✅ 正确写法(Jest):
test('calls fetch and returns data', async () => { fetch.mockResolvedValue({ ok: true, json: () => Promise.resolve({ message: 'ok' }) }); const result = await myApiCall(); expect(result.message).toBe('ok'); }); - ❌ 错误写法(忘记 await,测试会跳过断言):
test('...', () => { myApiCall().then(data => expect(data).toEqual(...)); // 不会等待,测试直接结束 }); - 验证 loading / error 状态:若组件有状态管理(如 React 的 useState),需触发重渲染并检查 DOM 或状态快照。
补充:Node.js 环境下需 polyfill fetch
Jest 默认运行在 Node.js,而 Node.js 原生无 fetch。可用 node-fetch 或 cross-fetch 补全:
- 安装:
npm install node-fetch --save-dev - 在
jest.setup.js中添加:global.fetch = require('node-fetch'); - 或使用 Jest 的
setupFiles配置自动加载
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










