Skip to content
返回项目教程

API Mock 服务器

从 OpenAPI 规范生成 mock API,配备有状态响应、故障注入和团队共享。

设计与 Schema

从 OpenAPI 规范定义 mock 路由,选择延迟和故障注入及存储模型。

为什么

Mock 服务器前置契约测试。前端和后端对着同一 OpenAPI mock 编码,集成从数周降到数天。故障注入(超时、500)在生产前捕获前端错误处理,生产修复成本高 10 倍。

何时使用

在前端和后端分歧之前。新 API 第一周从 OpenAPI 规范生成 mock。

如何做

1. 编写或获取 OpenAPI 规范 - 定义每个端点、请求/响应 schema 和状态码 - schema 中用 examples 提供真实 mock 数据 - 用 redocly 或 openapi-cli lint 校验 2. 生成 mock 服务器 - Prism:npx prism mock openapi.yaml -> 4010 端口即时 mock - MSW(Mock Service Worker):Storybook/测试中浏览器内 mock - WireMock:JVM 项目或独立 Docker 3. 用 Faker 加动态数据 - 列表用 Faker 生成值替换静态示例 - GET /users -> 25 个假用户含真实姓名/邮箱 - Faker 设种子以可复现测试 4. 设计故障注入 - 延迟:/slow 端点加 2 秒延迟测加载态 - 错误:/error 返回 500 测错误边界 - 经 header 配置:X-Mock-Status: 500 5. 规划存储模型 - 无状态(默认):每次请求返回新 Faker 数据 - 有状态:内存存储,POST 后 GET 返回创建项 - CRUD 演示和集成测试选有状态

示例

# openapi.yaml(节选) paths: /users: get: responses: "200": content: application/json: schema: { $ref: "#/components/schemas/UserList" } example: - { id: 1, email: "[email protected]", role: "admin" } post: requestBody: content: application/json: schema: { $ref: "#/components/schemas/NewUser" } responses: "201": content: application/json: schema: { $ref: "#/components/schemas/User" } # 生成 mock $ npx prism mock openapi.yaml [CLI] ✔ Prism 正在监听 http://localhost:4010 # GET /users -> 200 返回示例数组 # POST /users -> 201 返回生成的用户

常见问题

  • ⚠无 OpenAPI 规范——前端后端口头协议,一周内漂移,集成调试数天
  • ⚠仅静态示例——GET /users 永远返回同样 3 用户,隐藏分页和空态 bug
  • ⚠无故障注入——前端开发中从不见 500,上线无错误边界

最佳实践

  • ✓从 OpenAPI 规范生成 mock,非手写——规范是 mock 和服务器的唯一真源
  • ✓列表端点用 Faker,使分页、排序、空态可用真实数据量测试
  • ✓加故障注入 header(X-Mock-Status: 500),QA 无需改代码即可触发错误路径

实现与动态响应

构建有状态 mock、Faker 动态数据和条件路由,用于真实演示和测试。

为什么

前端需测试创建后列表流程时静态 mock 失效。有状态 mock(内存存储)让 CRUD 序列在 Storybook 和测试中端到端工作,无需后端,在进 staging 前捕获集成 bug。

何时使用

静态 mock 服务正常路径后。为 CRUD 演示和集成测试加有状态路由。

如何做

1. 建内存存储 - const db = { users: [], posts: [] }——重启重置 - 启动时用 Faker 生成 25 条种子 - 需跨重启则持久化到 JSON 文件 2. CRUD 接入存储 - GET /users -> db.users(分页:?page&limit) - POST /users -> 推入 db.users,返回 201 带新 id - PUT /users/:id -> 查找替换,缺失 404 - DELETE /users/:id -> 过滤移除,204 3. 加动态数据生成 - Faker.person.fullName()、Faker.internet.email() - 日期:Faker.date.recent({ days: 30 }) - 嵌套:帖子有作者(引用存储中的用户) 4. 经 header 条件路由 - X-Mock-Delay: 2000 -> 响应前 setTimeout 2 秒 - X-Mock-Status: 500 -> 返回 500 带错误体 - X-Mock-Empty: true -> 返回 [] 测空态 5. 集成前端测试套件 - Jest/Vitest 中 MSW:拦截 fetch,返回 mock 响应 - Storybook:MSW 插件让 story 命中 mock 非真实 API - 测试文件间重置存储避免交叉污染

示例

// Express + Faker 有状态 mock import express from "express"; import { faker } from "@faker-js/faker"; const app = express(); const db = { users: Array.from({ length: 25 }, (_, i) => ({ id: i + 1, name: faker.person.fullName(), email: faker.internet.email(), role: faker.helpers.arrayElement(["admin", "member"]), })) }; app.get("/users", (req, res) => { const { page = 1, limit = 10 } = req.query; const start = (page - 1) * limit; res.json({ data: db.users.slice(start, start + +limit), total: db.users.length }); }); app.post("/users", (req, res) => { const user = { id: db.users.length + 1, ...req.body }; db.users.push(user); res.status(201).json(user); }); // 经 header 故障注入 app.use((req, res, next) => { if (req.headers["x-mock-status"]) { return res.status(+req.headers["x-mock-status"]).json({ error: "mock" }); } next(); });

常见问题

  • ⚠CRUD 演示用无状态 mock——POST 后 GET 返回旧数据,演示像坏了
  • ⚠测试间不重置存储——测试 A 创建的用户泄漏到测试 B,导致不稳定失败
  • ⚠Faker 不设种子——每次运行数据变化,快照测试随机失败

最佳实践

  • ✓CRUD 端点用有状态内存存储,使创建后列表流程在演示和测试中可用
  • ✓测试文件间重置 mock 存储(beforeEach)防止交叉数据污染
  • ✓CI 中 Faker 设固定种子(faker.seed(123))使生成数据可复现

部署与共享

部署为 Docker 镜像、npm 包或托管服务,让全团队共享一个 mock。

为什么

Mock 服务器仅在全团队共用时有用。托管/共享 mock(Docker 镜像或提交到仓库的 MSW)确保前端、移动端、QA 对相同契约测试,消除'我机器上能跑'的集成失败。

何时使用

mock 正常路径稳定时。前端集成开始前打包,确保单一真源。

如何做

1. 打包为 Docker 镜像 - FROM node:20-alpine,复制 mock 服务器,CMD prism mock openapi.yaml - 推到 ghcr.io 或 Docker Hub,带 semver 标签 - 团队运行:docker run -p 4010:4010 ghcr.io/org/api-mock:1.2.0 2. 或将 MSW handlers 提交到仓库 - src/mocks/handlers.ts——提交、版本控制 - 前端在开发模式和测试中导入 handlers - OpenAPI 规范变更的同一 PR 更新 handlers 3. 部署共享托管实例 - Fly.io 或 Railway:部署 Prism 服务器,分享 URL - QA 和移动端指向此 URL 做手动测试 - 用简单 API key header 保护避免公开暴露 4. 保持 mock 与规范同步 - CI 步骤:每个 PR 从 openapi.yaml 重新生成 mock - 提交的 handlers 与规范偏离则构建失败 - 用 spectral lint 规范并阻断破坏性变更 5. 为团队写文档 - README:本地运行、注入故障、重置方法 - 加 /__reset 端点清除有状态存储,演示间用 - 列出可用 X-Mock-* header 及示例

示例

# Dockerfile FROM node:20-alpine WORKDIR /app COPY openapi.yaml . RUN npm install -g @stoplight/prism-cli EXPOSE 4010 CMD ["prism", "mock", "openapi.yaml", "-h", "0.0.0.0"] # CI:重新生成 mock + lint 规范(GitHub Actions) - name: Lint OpenAPI run: npx @redocly/cli lint openapi.yaml - name: 检查 handlers 同步 run: npx openapi-typescript openapi.yaml -o src/api/types.ts && git diff --exit-code src/api/types.ts # Fly.io 共享实例 $ fly deploy --image ghcr.io/org/api-mock:1.2.0 -> https://api-mock.fly.dev(分享给 QA + 移动团队)

常见问题

  • ⚠每人跑不同 mock 版本——前端测试通过,集成失败因契约漂移
  • ⚠无 CI 检查规范-handler 同步——handlers 过期,mock 返回真实 API 已无的字段
  • ⚠共享 mock 公开暴露无认证——有人发现并探测你的 API 面

最佳实践

  • ✓将 MSW handlers 提交到仓库,与 OpenAPI 规范同 PR 更新——单一真源
  • ✓加 CI 步骤从规范重新生成类型并在 diff 时失败——自动捕获规范-handler 漂移
  • ✓任何共享托管 mock 用 API key header 保护,无认证不部署到公开域名

完整开发者生命周期

从想法到维护的 14 阶段开发者路径图 — 可视化依赖关系、追踪进度。

下一步