js接口测试核心是用msw拦截fetch请求并返回模拟响应,无需修改业务代码;也可用jest mock全局fetch作轻量方案;需覆盖状态码、json解析异常、网络错误等分支。

在 JS 项目中用 Fetch 做异步接口测试,核心是**绕过真实网络请求,用模拟响应替代后端服务**,同时保持调用方式和生产代码一致。不需要改业务里的 fetch 调用,只需在测试环境拦截并返回预设数据。
用 Mock Service Worker(MSW)拦截请求
这是目前最推荐的方式,它在浏览器或 Node.js 环境下都能运行,且不污染全局 fetch,对测试友好。
- 安装依赖:
npm install msw msw-node --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/login', (req, res, ctx) => { const { username } = await req.json(); return username === 'test' ? res(ctx.status(200), ctx.json({ token: 'fake-jwt' })) : res(ctx.status(401), ctx.json({ error: 'Unauthorized' })); }) ]; - 在测试文件中启动 worker 并清理:
import { setupServer } from 'msw/node'; import { handlers } from './mocks/handlers'; const server = setupServer(...handlers); beforeAll(() => server.listen()); afterEach(() => server.resetHandlers()); afterAll(() => server.close());
用 Jest 的全局 fetch 模拟(轻量方案)
适合简单场景或快速验证,但需注意:它会覆盖全局 window.fetch,且无法区分不同 URL 或方法。
将一个或多个视频上传至YouTube。当用户想“上传到YouTube”“发YouTube”“批量上传”“upload to YouTube”“post videos to YouTube”或发布到YouTube时使用此技能。
- 在测试前 mock fetch:
global.fetch = jest.fn() .mockResolvedValueOnce({ ok: true, status: 200, json: () => Promise.resolve([{ id: 1, title: 'Test Post' }]) }) .mockResolvedValueOnce({ ok: false, status: 500, json: () => Promise.resolve({ error: 'Server error' }) }); - 确保业务函数实际调用了 fetch,并等待 Promise 完成:
test('fetches posts successfully', async () => { const data = await fetchPosts(); // 假设这是封装了 fetch 的函数 expect(data).toEqual([{ id: 1, title: 'Test Post' }]); });
测试关键点不能漏
只测“能拿到数据”不够,要覆盖真实使用中的典型分支:
-
HTTP 状态码处理:显式检查
response.ok或response.status,比如 401 时跳转登录、404 时提示不存在 -
JSON 解析失败兜底:用
try/catch包裹response.json(),防止后端返回非 JSON 内容导致未捕获异常 -
网络错误场景:MSW 可用
ctx.networkError()模拟断网;Jest mock 可返回 rejected Promise -
请求头与 body 校验(进阶):MSW 的
req.headers.get('Authorization')和req.json()可断言是否携带 token 或参数正确
配合 async/await 写清晰的测试用例
避免混用 .then() 和 await,统一风格提升可读性。例如:
test('handles login failure', async () => {
const result = await loginUser('wrong', 'pass');
expect(result.success).toBe(false);
expect(result.message).toBe('Invalid credentials');
});
只要业务层用的是标准 fetch + async/await,测试时就能自然等待、精准断言,不用额外加 waitFor 或定时器。










