当后端還没准備好、而前端又等不起时,模拟資料 API 就是答案。Mock API 让前端团隊可以基于稳定的契约交付 UI,而真實后端可以慢慢赶上;让移动端開發者無需真實授权令牌就能偵錯應用;也让任何人——尤其是 QA 团隊——不必等待预發佈环境部署就能測試新功能。本教學将介绍三种能力逐级增强的 Mock 模式,最后演示如何直接把 USA Data Tools REST API 当作模拟后端使用。
為什么需要 Mock API?
- 并行工作:前后端团隊约定好契约;前端 Mock 它,后端實現它,双方交付都更快。
- 确定性:稳定的 Mock 每次運行都返回相同的資料,消除不稳定的測試。
- 邊缘情况:Mock 可以刻意返回 500 和 422,让你的錯誤處理代碼变得可測試。
- 隱私:迭代過程中没有真實客户資料离開生產环境。
模式一——静态托管的 JSON 檔案
最簡单的 Mock 就是一個由任意静态 HTTP 伺服器托管的 JSON 檔案目录。它適合只读端點。
mock-api/
users.JSON
users.42.JSON
addresses.JSON
用你喜欢的任何工具托管——Python 的 http.server、VS Code Live Server,或一行命令的 Vite 静态目录。前端代碼通過环境变量要求 /mock-api/users.JSON 而不是 /api/users,这样之后可以切换基础 URL。
const API_BASE = process.env.REACT_APP_API_BASE || "/mock-api";
const users = await fetch(`${API_BASE}/users.JSON`).then(r => r.JSON());
局限:没有单條記錄端點、没有分頁、没有 PUT/POST。这种模式能覆蓋 70% 的前端工作(列表和详情頁),然后就力不从心了。
模式二——一個轻量 Node/Express 伺服器
對于剩下的場景,写一個 50 行的 Express 伺服器,用真實的 HTTP 语義返回夹具資料。状态碼、查詢参数解析和幂等的 POST 處理都免費獲得。
// mock-server/server.js
import express from "express";
import { readFileSync } from "node:fs";
const users = JSON.parse(readFileSync("./fixtures/users.JSON", "utf8"));
const addresses = JSON.parse(readFileSync("./fixtures/addresses.JSON", "utf8"));
const app = express();
app.use(express.JSON());
// 带分頁 + 搜索的列表
app.get("/api/users", (req, res) => {
const page = Number(req.query.page ?? 1);
const size = Number(req.query.size ?? 20);
const q = (req.query.q ?? "").toLowerCase();
const filtered = users.filter(u =>
!q || u.name.toLowerCase().includes(q) || u.email.includes(q)
);
const start = (page - 1) * size;
const data = filtered.slice(start, start + size);
res.JSON({
data,
page,
size,
total: filtered.length,
});
});
// 单條記錄
app.get("/api/users/:id", (req, res) => {
const user = users.find(u => u.id === Number(req.params.id));
if (!user) return res.status(404).JSON({ error: "not found" });
res.JSON(user);
});
app.listen(8081, () => console.log("Mock API on http://localhost:8081"));
这個實現為前端团隊提供了真實的 HTTP 语義——查詢参数、状态碼、content-type——代价只是大约一小时的敲键盘时间。
模式三——持续產生新鲜資料的 Mock
静态夹具会過时;上個 Sprint 的 10 條測試資料已经無法测出你刚做的無限滚动分頁。使用 USA Data Tools API 按需為你的 Mock 填充資料。
// 每次 Mock 伺服器啟动时獲取 50 條新鲜的美國記錄
async function seedAddresses(count = 50) {
const r = await fetch(
`https://vic999.com/us-address/api/v1/address?count=${count}`,
{ headers: { Authorization: `Bearer ${process.env.USA_KEY}` } }
);
if (!r.ok) throw new Error(`seed failed: ${r.status}`);
const { data } = await r.JSON();
return data.map((a, i) => ({ id: i + 1, ...a }));
}
let cache = [];
app.get("/api/addresses", async (req, res) => {
if (cache.length === 0) cache = await seedAddresses(50);
res.JSON({ data: cache });
});
第一個要求到来时,Mock 会懒載入 50 條真實地址(郵遞區號+州地理一致、区号有效的電話),然后从快取中提供服务。重啟 Mock 就能獲得一批新資料——当你想要預設确定性、但每個 Sprint 又想要不同資料形態时非常有用。
提供邊缘情况的回應
一個永远只返回 200 OK 的 Mock 测不出錯誤路径。用一個查詢参数做分支,让測試可以選擇進入失败模式:
app.get("/api/users/:id", (req, res) => {
if (req.query._force === "500") {
return res.status(500).JSON({ error: "forced_error" });
}
if (req.query._force === "slow") {
return setTimeout(() => res.JSON(users[0]), 5000);
}
const user = users.find(u => u.id === Number(req.params.id));
if (!user) return res.status(404).JSON({ error: "not_found" });
res.JSON(user);
});
現在你的前端測試可以要求 ?_force=500 来驗證錯誤邊界 UI 是否出現,或用 ?_force=slow 驗證載入指示器是否显示。仅此一個模式就能堵住大多数前端的健壮性缺口。
為 Mock 契约编写文档
Mock 最大的成本是與真實后端之间的漂移。為 Mock 伺服器配一份 OpenAPI 规范——哪怕手写——并双向驗證:
- 从规范產生 Mock 回應(運行时返回符合 Schema 的資料)。
- 在 CI 中用规范校驗真實后端(一個便宜的契约測試)。
一旦 Mock 與真實后端使用同一套 Schema,前端不在乎自己正在跟哪一個對話。
npx @stoplight/spectral-cli lint openapi.yaml --ruleset spectral:oas
接入 CI
jobs:
front-end-e2e:
runs-on: ubuntu-latest
services:
mock:
image: node:20
options: --entrypoint node
env:
USA_KEY: ${{ secrets.USA_KEY }}
ports: ["8081:8081"]
steps:
- uses: actions/checkout@v4
- run: npm ci
- run: npm run start:mock &
- run: npx playwright test
- run: npx @stoplight/spectral-cli lint openapi.yaml
Mock 作為服务啟动,前端測試针對它運行,契约检查会在规范漂移时發出警告。当真實后端就绪后,切换环境变量即可——只要契约是诚實的,同样的測試就能通過。
三种方案如何取舍
| 模式 | 最適合 | 成本 |
|---|---|---|
| 静态 JSON | 只读的列表/详情 UI | 成本最低 |
| 轻量 Express 伺服器 | POST/PUT、分頁、搜索 | 一個下午 |
| USA API 填充資料 | 真實的大資料集 | API 密钥 + 50 行代碼 |
跨团隊交接
当后端团隊准備就绪时,前端的 Mock 就变成了回归測試套件。经過 spectral 校驗的规范成為契约;前端的 Playwright 套件针對真實后端運行,暴露任何漂移(“后端新增了必填欄位”)。这就是為什么契约比 Mock 更重要——但 Mock 让你从第一天起就能開始检驗契约。
提示:Mock 伺服器天然是短命的。当真實后端上線后,不要扔掉 Mock——让它继续在仅本地可達的端口上運行,用于快速的离線迭代,以及故意触發那些真實后端不会按需產生的失败場景。
全新 SaaS 項目的實用配方
如果你从零開始:
- 為你需要的前 5 個端點编写 OpenAPI 规范。
- 啟动由 USA Data Tools 地址 API 填充資料的 Express Mock 伺服器。
- 通過
API_BASE环境变量把前端接上去。 - 新增
?_force=技巧,用于慢速/500/超时場景。 - 在 Mock 和真實后端的 CI 中都運行
spectrallint 作為契约測試。
这套模式在我们的項目中经受了多年的考驗,可以从一個前端開發者扩展到 20 人的团隊,而無需改变架构。
总結
模拟資料 API 不是走捷径——它是团隊之间的交付契约,让所有人都能并行推進。先用几個 JSON 檔案起步,需要 HTTP 语義时升級到 Express 伺服器,再用地址產生器填充真正能测出邊缘情况的資料集。搭配一個经過 Spectral 校驗的 OpenAPI 规范,等真實后端就绪时,同一套測試無需任何重写即可直接運行。