mock 的核心是“像、稳、易维护”,需明确边界(如接口未就绪、异常场景宜mock,已联调稳定接口不宜)、分阶段选工具(mock.js/json-server→msw→jest.mock→cy.intercept)、严控数据细节(字段缺失、类型漂移、分页结构、时间格式),并持续维护(注释、版本映射、ci校验、提测前冒烟测试)。

Mock 是前端开发中绕不开的环节,尤其在接口未就绪、联调未开始或需要复现特定响应场景时。但写得随意,轻则导致测试失效、逻辑误判,重则掩盖真实问题、上线后暴雷。关键不是“能不能 mock”,而是“mock 得像不像、稳不稳、好不好维护”。
明确 Mock 边界:什么该 mock,什么不该
Mock 的核心目标是隔离依赖、聚焦当前模块逻辑。以下情况适合 mock:
- 后端接口尚未提供(如 Swagger 文档未定稿)
- 需稳定复现异常路径(如 401 登录过期、503 服务不可用、空列表、超长字段)
- 耗时操作(如文件上传、大分页查询)影响本地调试效率
- 涉及敏感数据或权限校验,本地无法真实触发
这些情况不宜 mock:
- 已联调通过且稳定的公共基础接口(如用户信息、字典项),mock 反而增加不一致风险
- 强依赖时序或状态流转的接口(如 WebSocket 推送 + HTTP 回调组合),mock 难以保真
- 纯 UI 层组件(如按钮、图标),无需 mock 数据,用 props 直接传入即可
选对工具链:按阶段匹配方案
不同阶段对 mock 的诉求不同,硬套一套方案容易踩坑:
- 开发初期(接口未定义):用 Mock.js 或 json-server 快速搭静态响应,重点在字段结构和类型占位,不追求逻辑分支
- 联调准备期(接口文档已出):用 msw(Mock Service Worker) 拦截真实 fetch/fetch-like 请求,支持动态响应、延迟、错误注入,与生产请求代码零侵入
- 单元测试中:用 jest.mock() 或 vitest.mock() 替换模块导出,精准控制返回值,避免网络依赖
- E2E 测试(如 Cypress):优先使用其内置 cy.intercept(),可 stub 响应、等待请求、甚至修改请求头,比全局 mock 更可控
写好 Mock 数据:从“能跑”到“防错”
很多 bug 源于 mock 数据太理想化。真实接口常有这些细节:
- 字段缺失或为 null:后端字段可能临时下线或未填充,mock 中别默认全量返回,可随机 omit 1–2 个非必填字段
- 类型漂移:如 id 字段文档写 string,实际返回 number;mock 时保留原始类型,必要时加注释说明兼容逻辑
-
分页结构不一致:有的接口用
{ list: [], total: 100 },有的用{ data: { items: [], pagination: { total: 100 } } },mock 必须严格对齐约定格式 - 时间格式混杂:ISO 8601、时间戳、秒级/毫秒级、带有时区,mock 中统一用文档指定格式,避免本地 new Date() 生成造成时区偏差
持续维护要点:别让 Mock 成技术债
Mock 文件容易写完就扔,结果越积越多、越来越假。守住这几条线:
- 所有 mock 响应必须附带简短注释,说明对应接口路径、用途(如 “模拟登录失败:密码错误”)、是否已与后端对齐
- 建立 mock 版本映射表(如 JSON 文件或 README 表格),记录每个 mock 规则适用的 API 文档版本号或 PR 编号
- CI 中加入简单校验:比如扫描所有 mock 文件,检查是否包含未使用的响应规则、是否存在硬编码的生产域名
- 每次提测前,把 mock 切换为真实接口跑一轮 smoke test,确认字段、状态码、结构无差异











