js中mock高级模式核心是可控交互,即精准控制依赖行为、隔离副作用、验证调用逻辑,用于覆盖异步流程、第三方集成等难测场景。

JS 中 Mock 模拟高级编程模式,核心不在“造假数据”,而在“可控交互”——即精准控制依赖行为、隔离副作用、验证调用逻辑。它常用于测试异步流程、第三方服务集成、状态边界条件等真实场景难以覆盖的环节。
掌握 Mock 的关键能力点
不是记住 API,而是理解三类控制能力:
-
行为模拟:用
jest.fn()或sinon.stub()替换函数,返回预设值、抛出错误、或动态响应参数(如mockImplementation((x) => x * 2)) -
调用断言:验证是否被调用、调用次数、传入参数(
toBeCalledTimes(1)、toHaveBeenCalledWith('id-123'))、甚至调用顺序(toHaveBeenNthCalledWith(2, 'timeout')) -
模块级替换:用
jest.mock('./api')拦截整个模块,或用jest.doMock()实现按需局部 mock,避免污染全局测试环境
从简单到复杂:三个进阶台阶
初学容易卡在“能 mock”,但高级用法体现在“何时不 mock”和“如何分层 mock”:
将一个或多个视频上传至YouTube。当用户想“上传到YouTube”“发YouTube”“批量上传”“upload to YouTube”“post videos to YouTube”或发布到YouTube时使用此技能。
-
第一层:函数级打桩 —— 替换单个工具函数(如
fetch、localStorage.setItem),验证组件在不同返回值下的渲染分支 -
第二层:模块依赖解耦 —— 对接外部 SDK(如支付网关、地图 API)时,mock 其导出对象,让业务逻辑测试不依赖网络或密钥;注意保留类型定义(TypeScript 下可用
jest.Mocked<typeof module></typeof>) - 第三层:行为驱动模拟(Behavior-Driven Mocking) —— 根据测试用例意图定制响应:例如模拟“首次失败、重试成功”,或“并发请求下返回乱序响应”,直接驱动状态机或副作用逻辑的完整性验证
避开常见认知陷阱
很多开发者把 mock 当成“绕过问题”的手段,结果写出脆弱测试:
-
不 mock 实际会执行的副作用 —— 比如 mock 了
console.log却没 mocksetTimeout,导致异步逻辑未被覆盖 - 过度 mock 导致测试失真 —— 把本该由真实模块协作完成的流程,全用 mock 拼凑,反而掩盖了集成缺陷
-
忽略清理机制 —— 每次测试后未调用
jest.clearAllMocks()或mockReset(),导致 mock 状态跨测试用例污染
实战建议:从一个真实场景切入
比如测试一个带重试机制的数据加载 Hook:
- 先 mock
fetch返回失败响应,验证 loading 状态与错误提示 - 再 mock 它首次拒斥、第二次 resolve,检查重试计数与最终数据更新
- 最后 mock 一个永远 pending 的 fetch,验证超时逻辑是否触发 abortController
这样每步都对应明确的行为契约,mock 就成了表达需求的语言,而不是技术负担。










