MSW 处理器

REST 处理器

// src/mocks/handlers.ts import { http, HttpResponse } from 'msw' export const handlers = [ http.get('/api/users', () => { return HttpResponse.json([ { id: 1, name: '张三', email: '[email protected]' }, { id: 2, name: '李四', email: '[email protected]' }, ]) }), http.get('/api/users/:id', ({ params }) => { const { id } = params if (id === '999') { return new HttpResponse(null, { status: 404 }) } return HttpResponse.json({ id: Number(id), name: '张三' }) }), http.post('/api/users', async ({ request }) => { const body = await request.json() return HttpResponse.json({ id: 3, ...body }, { status: 201 }) }), ]

GraphQL 处理器

import { graphql, HttpResponse } from 'msw' export const handlers = [ graphql.query('GetUser', ({ variables }) => { return HttpResponse.json({ data: { user: { id: variables.id, name: '张三' }, }, }) }), graphql.mutation('CreateUser', async ({ variables }) => { return HttpResponse.json({ data: { createUser: { id: 99, ...variables }, }, }) }), ]

Node.js 配置 — Jest 集成

// src/mocks/server.ts import { setupServer } from 'msw/node' import { handlers } from './handlers' export const server = setupServer(...handlers) // jest.setup.ts import { server } from './src/mocks/server' beforeAll(() => server.listen({ onUnhandledRequest: 'error' })) afterEach(() => server.resetHandlers()) afterAll(() => server.close()) // 在测试中覆盖处理器 test('API 失败时显示错误', async () => { server.use( http.get('/api/users', () => { return HttpResponse.json({ error: '服务器错误' }, { status: 500 }) }) ) render(<UserList />) await waitFor(() => screen.getByText('加载用户失败')) })

高级响应解析器

import { http, HttpResponse, delay } from 'msw' export const handlers = [ // 模拟延迟 http.get('/api/slow', async () => { await delay(1500) return HttpResponse.json({ data: '慢响应' }) }), // 自定义响应头 http.get('/api/data', () => { return new HttpResponse(JSON.stringify({ items: [] }), { status: 200, headers: { 'X-Total-Count': '42' }, }) }), // 模拟网络错误 http.get('/api/broken', () => { return HttpResponse.error() }), // 读取查询参数 http.get('/api/search', ({ request }) => { const url = new URL(request.url) const q = url.searchParams.get('q') return HttpResponse.json([{ id: 1, title: `${q} 的搜索结果` }]) }), ]

浏览器配置

// npx msw init public/ --save // src/mocks/browser.ts import { setupWorker } from 'msw/browser' import { handlers } from './handlers' export const worker = setupWorker(...handlers) // src/main.tsx async function enableMocking() { if (process.env.NODE_ENV !== 'development') return const { worker } = await import('./mocks/browser') return worker.start({ onUnhandledRequest: 'warn' }) } enableMocking().then(() => { ReactDOM.createRoot(document.getElementById('root')!).render(<App />) })

Browser vs Node 对比

环境配置方式适用场景
浏览器setupWorker + Service Worker开发环境、Storybook
Node.jssetupServer + 拦截器Jest 单元/集成测试
Playwrightpage.route() 或 HTTP 中间件E2E 测试