mock是用可控“假对象”替代真实依赖(如api、数据库),切断外部连接以聚焦被测逻辑;解决网络不稳定、数据不可控、费用/耗时高、时间难断言等测试痛点。

JS 中的 Mock 模拟,是指用一个可控的“假对象”替代真实依赖(比如 API 调用、数据库操作、定时器、时间函数等),让被测代码在不触发实际副作用的前提下运行。它的核心作用不是“造个能用的对象”,而是切断与外部世界的连接,把测试焦点牢牢锁在当前函数或类本身的逻辑上。
Mock 解决了哪些真实痛点
没有 Mock 时,单元测试容易受这些干扰:
- 网络请求失败导致测试随机失败(如接口超时、服务宕机)
- 数据库状态不可控(数据被其他测试污染、初始化耗时)
- 第三方服务限流或收费(比如调一次短信接口就扣费)
- 时间相关逻辑难断言(如
new Date()返回值每次不同) - 异步依赖嵌套深,回调难追踪、难复现
Mock 如何实现依赖隔离
关键不在“替换”,而在“接管行为”:
- 用
jest.mock()或sinon.stub()替换模块导出,让fetch或axios.get不发真实请求,而是返回预设 JSON - 对类方法打桩(Stub),比如让
UserService.getUserById()总是返回{ id: 1, name: 'Alice' },跳过数据库查询 - 用 Spy 记录调用痕迹,验证某个函数是否被传入特定参数调用过,而不关心它内部怎么执行
- 主动抛出错误,模拟网络异常、权限拒绝等边界场景,测试错误处理分支是否健壮
一个典型例子:测试带 API 调用的 React Hook
假设有个自定义 Hook useUserProfile(id),内部用 fetch 获取用户数据。不 Mock 时,每次测试都发真实请求;加 Mock 后:
- 全局拦截
fetch,让它对匹配/api/users/123的请求返回固定响应 - 组件渲染后,可断言 UI 是否显示 “加载中” → “用户名:Tom” → 状态是否正确更新
- 再换一个 Mock 响应,模拟 404,验证是否显示错误提示
Mock 不是万能,但它是可控测试的前提
它不验证集成是否通、API 格式是否最新、数据库索引是否合理——那些属于集成测试或 E2E 测试的范畴。Mock 只确保:当输入确定、依赖行为被锁定时,我的这段逻辑一定按预期工作。 这种确定性,是自动化测试、CI 流水线和快速迭代的基础。











