Mock Service Worker (MSW) logo

Mock Service Worker (MSW)

通过在网络层拦截请求的 API Mock 库

精选工具MockAPI MockService Worker网络拦截

面向浏览器和 Node.js 的 API Mock 库,通过在**网络层**拦截 HTTP 请求,让应用代码无感知地使用 Mock 响应。MSW 2.x 基于标准 Fetch API 原语重构,同一套 handler 可在开发、单元测试、E2E 测试和 Storybook 中复用,是前端 API Mock 领域的事实标准。

Mock Service Worker 前端 API Mock 技术调研

Mock Service Worker(MSW)是面向浏览器和 Node.js 的 API Mock 库,通过在网络层拦截 HTTP 请求,让应用代码无感知地使用 Mock 响应。MSW 2.x 基于标准 Fetch API 原语重构,同一套 handler 可在开发、单元测试、E2E 测试和 Storybook 中复用,是前端 API Mock 领域的事实标准。


一、 基本信息

维度关键指标 / 描述
技术标签API Mock / Service Worker / 网络拦截 / 测试 / 开发调试
开发商MSW 开源社区(mswjs)
官方网站https://mswjs.io/
GitHub 仓库mswjs/msw
npm 包msw
许可协议MIT License
首次发布2018 年
当前版本MSW 2.x(2024 年发布,2026 年持续维护)
运行要求Node.js 18+(MSW 2.x)
生态成熟度高(前端测试与 Mock 首选方案之一)

二、 技术定位与简介

MSW 的核心理念是 「独立 API Mock 层」

  • 不 patch fetchaxios 等客户端库,应用在真实网络栈上运行。
  • 浏览器端通过 Service Worker 拦截出站请求。
  • Node.js 端通过 @mswjs/interceptors 在更低层拦截。
  • 使用标准 Request / Response / HttpResponse,与 Fetch API 对齐。

MSW 特别适合:

  • 前端在后端未就绪时并行开发。
  • 单元/集成/E2E 测试中稳定 Mock API。
  • Storybook 中展示组件的不同数据状态。
  • 演示和原型开发无需真实后端。

三、 快速上手安装说明

1. 安装

pnpm add -D msw

2. 初始化 Service Worker(浏览器)

npx msw init public/ --save

3. 定义 Handlers

// src/mocks/handlers.ts
import { http, HttpResponse } from 'msw'
 
export const handlers = [
  http.get('/api/users', () => {
    return HttpResponse.json([
      { id: '1', name: 'Alice' },
      { id: '2', name: 'Bob' }
    ])
  }),
 
  http.post('/api/users', async ({ request }) => {
    const body = await request.json()
    return HttpResponse.json({ id: '3', ...body }, { status: 201 })
  })
]

4. 浏览器环境启动

// src/mocks/browser.ts
import { setupWorker } from 'msw/browser'
import { handlers } from './handlers'
 
export const worker = setupWorker(...handlers)
// src/main.ts(仅开发环境)
async function enableMocking() {
  if (import.meta.env.DEV) {
    const { worker } = await import('./mocks/browser')
    await worker.start({ onUnhandledRequest: 'bypass' })
  }
}
 
enableMocking().then(() => {
  // 启动应用
})

5. Node.js / Vitest 环境

// src/mocks/server.ts
import { setupServer } from 'msw/node'
import { handlers } from './handlers'
 
export const server = setupServer(...handlers)
// vitest.setup.ts
import { beforeAll, afterEach, afterAll } from 'vitest'
import { server } from './src/mocks/server'
 
beforeAll(() => server.listen())
afterEach(() => server.resetHandlers())
afterAll(() => server.close())

四、 核心特性

1. 网络层拦截

请求经过完整应用代码路径后才被拦截,测试更贴近真实行为。

2. 同构 Handlers

同一套 handlers 在浏览器和 Node.js 中复用。

3. REST 与 GraphQL 支持

import { graphql, HttpResponse } from 'msw'
 
graphql.query('GetUser', () => {
  return HttpResponse.json({
    data: { user: { id: '1', name: 'Alice' } }
  })
})

4. 路径参数与查询参数

http.get('/api/users/:id', ({ params }) => {
  return HttpResponse.json({ id: params.id, name: 'Alice' })
})

5. 动态与条件响应

http.get('/api/posts', ({ request }) => {
  const url = new URL(request.url)
  const page = url.searchParams.get('page') ?? '1'
  return HttpResponse.json({ page, items: [] })
})

6. per-test 覆盖

server.use(
  http.get('/api/users', () => {
    return HttpResponse.json([], { status: 500 })
  })
)

7. 延迟与错误模拟

http.get('/api/slow', async () => {
  await delay(2000)
  return HttpResponse.json({ ok: true })
})

8. MSW 2.x Fetch API 对齐

使用 http 替代旧版 restHttpResponse 替代 res(ctx.json())


五、 适用场景

1. 黄金适用场景

  • 前端开发时后端 API 未就绪。
  • Vitest/Jest 单元与集成测试。
  • Playwright/Cypress E2E 测试中的 API Mock。
  • Storybook 组件展示多种数据状态。
  • 演示和培训环境。
  • 测试边界情况(500 错误、超时、空数据)。

2. 局限适用场景

  • 需要 GUI 手动调试 API 请求(用 Postman/Apifox)。
  • 非 HTTP 协议(原生 WebSocket 需额外处理)。
  • 团队不愿引入 Service Worker 的项目。
  • 需要持久化 Mock 数据服务(考虑 json-server 或后端 Mock)。

六、 技术亮点

1. 零侵入应用代码

不修改 fetch/axios 调用,Mock 与实现解耦。

2. 单一事实来源

开发、测试、文档共用同一套 handlers。

3. 标准 Web API

基于 Fetch API,学习成本低,与平台演进一致。

4. 框架无关

支持 React、Vue、Angular、Svelte 及任意请求客户端。

5. MSW 2.0 架构升级

ESM 原生、更好的 Node 拦截、移除 polyfill 依赖。


七、 核心概念与架构

digraph MSW_Architecture {
  rankdir=LR
  node [shape=box, style="rounded,filled", fillcolor="#f0f9ff"]
  App [label="Application Code\n(fetch/axios/query)", fillcolor="#bae6fd"]
  Network [label="Network Layer"]
  SW [label="Service Worker\n(Browser)"]
  Interceptor [label="@mswjs/interceptors\n(Node.js)"]
  Handlers [label="Request Handlers"]
  Response [label="Mock Response"]
 
  App -> Network
  Network -> SW
  Network -> Interceptor
  SW -> Handlers
  Interceptor -> Handlers
  Handlers -> Response
  Response -> App
}

八、 技术局限与边界

  1. Service Worker 仅限 HTTPS/localhost:生产环境通常只在开发/测试启用。
  2. 首次注册有延迟:Service Worker 激活需要页面刷新或等待。
  3. WebSocket 支持有限:主要面向 HTTP/GraphQL。
  4. 团队需统一 Mock 数据维护:handlers 需与 API 契约同步更新。
  5. 不替代 API 设计工具:无 GUI 请求构建器。
  6. Node 18+ 要求:旧 Node 版本不支持 MSW 2.x。

九、 生态地图

digraph MSW_Ecosystem {
  rankdir=TB
  node [shape=box, style="rounded,filled", fillcolor="#f0f9ff"]
  MSW [label="MSW", fillcolor="#bae6fd"]
 
  MSW -> Vitest [label="Vitest"]
  MSW -> Jest [label="Jest"]
  MSW -> Playwright [label="Playwright"]
  MSW -> Cypress [label="Cypress"]
  MSW -> Storybook [label="Storybook"]
  MSW -> Vite [label="Vite Dev"]
  MSW -> Interceptors [label="@mswjs/interceptors"]
  MSW -> Faker [label="@faker-js/faker"]
}

十、 生态集成

集成方向工具/方案说明
单元测试Vitest / JestsetupServer 在测试中启用 Mock。
E2E 测试Playwright / Cypress浏览器中启动 worker 或使用 Node server。
组件开发Storybookmsw-storybook-addon 按 story 配置 handlers。
开发服务器Vite / Next.js开发环境条件启动 worker。
假数据@faker-js/faker在 handlers 中生成逼真 Mock 数据。
API 契约OpenAPI / Zod从 schema 生成或校验 Mock 响应。

十一、 开发与工程化

1. 目录结构建议

src/mocks/
  handlers/
    users.ts
    posts.ts
  handlers.ts      # 聚合导出
  browser.ts       # setupWorker
  server.ts        # setupServer

2. 与 OpenAPI 结合

从 OpenAPI 规范生成初始 handlers,或用手动 handlers 保持与契约一致。

3. CI 中启用

Vitest setup 中 server.listen(),确保 CI 不依赖真实 API。

4. onUnhandledRequest 策略

  • bypass:未匹配请求放行(开发常用)。
  • warn:控制台警告。
  • error:测试环境严格模式,防止意外真实请求。

十二、 性能与安全

1. 性能关注点

  • Service Worker 拦截开销通常可忽略。
  • 大量 handlers 时注意匹配顺序和正则性能。
  • 测试后 server.resetHandlers() 避免用例间污染。

2. 安全关注点

  • 生产构建排除 MSW:条件导入,tree-shake 开发代码。
  • Mock 数据不应包含真实 PII 或生产密钥。
  • 勿在生产环境注册 Service Worker Mock。
  • handlers 中的动态逻辑注意 XSS(若返回 HTML)。

十三、 技术对比

工具定位优势局限适合选择
MSW网络层 API Mock同构、零侵入、测试复用无 GUI、需维护 handlers前端开发与测试
Mirage JS客户端 Mock 服务器关系型假数据库、ORM 风格较老、生态萎缩遗留项目
json-serverREST Mock 服务器真实 HTTP 服务、零代码需独立进程、功能简单快速原型
Postman Mock云端 Mock与 Collection 集成需网络、非代码内 Mock团队协作联调
Apifox Mock一体化 Mock与文档同步平台绑定国内团队

十四、 最佳实践

  1. handlers 按资源拆分文件,在 handlers.ts 聚合。
  2. 开发与测试共用 handlers,避免两套 Mock 漂移。
  3. 测试用 server.use() 覆盖边界场景,不污染全局 handlers。
  4. 开发环境 onUnhandledRequest: 'bypass',测试环境 'error'
  5. 与 API 契约同步更新,Mock 过期比无 Mock 更危险。
  6. 生产构建确保 tree-shake MSW 启动代码
  7. Storybook 按 story 配置 handlers,展示空态/错误态。
  8. 结合 faker 生成数据,但保持字段与真实 API 一致。
  9. E2E 优先 MSW 稳定数据,减少 flaky 测试。
  10. 文档化 Mock 场景,让新成员理解可用 endpoints。

十五、 学习与社区资源