Jest Mock 的核心是精准拦截并替换被测模块直接调用的函数,返回可控结果,避免触碰底层依赖;需在 import 前声明 mock,优先使用工厂函数实现部分替换,结合依赖注入提升可测性,并在 beforeEach 中调用 jest.clearAllMocks() 及时清理状态。

在 JS 单元测试中用 Jest Mock 替换外部依赖,核心不是“删掉真实代码”,而是让被测模块调用的函数返回你控制的结果,同时不发请求、不读文件、不连数据库。关键在于拦截点要准、替换方式要稳、清理要及时。
优先 mock 你直接调用的那一层
别去 patch XMLHttpRequest 或重写 fetch 底层逻辑。Jest 支持精准拦截你业务里真正写的那一行:
- 如果你写了
axios.get('/user'),就 mockaxios.get,而不是它内部用的http模块 - 如果你封装了
apiClient.fetchUser(),就 mock 这个方法本身,而不是它内部怎么发请求 - 避免 mock 未导出的私有函数或模块内部变量——重构时测试会立刻崩
顶层 mock + 工厂函数实现部分替换
Jest 的 jest.mock() 必须写在 import 语句之前,才能生效。想只 mock 某几个方法、保留其余真实逻辑,用 factory 函数:
DMap GL地图JSAPI(dmapgl)开发指南。用于编写、审查、调试 DMap 地图 API 代码,涵盖地图初始化、覆盖物渲染、图层管理、事件处理、控件交互等任务。当用户提及 dmap、dmapgl、jsapi‑gl 或相关地图开发需求时自动触发。
- 在测试文件顶部写:
jest.mock('./api', () => { const actual = jest.requireActual('./api'); return { ...actual, fetchUser: jest.fn().mockResolvedValue({ id: 1 }) }; }); - 这样
fetchPost和utils还走真实代码,只有fetchUser被接管 - 注意路径必须和
import完全一致(包括.js扩展名)
用依赖注入让 mock 更自然
与其在测试里“硬塞” mock,不如让业务代码天生支持替换:
- 把请求函数作为参数传入:比如
function loadUser(requestFn) { return requestFn('/api/user'); } - 组件或 Hook 中默认用
fetch,测试时传mockFetch,生产环境完全不用改 - 服务类构造器接收
httpClient实例,测试时给个带get方法的对象就行 - 配合 TypeScript 接口(如
interface HttpClient { get(url: string): Promise<any> }</any>),类型更安全,替换更放心
每次测试后清理 mock 状态
不清理会导致测试间相互影响,比如上一个 test 把 axios.get 设成失败,下一个 test 就莫名其妙报错:
- 在
beforeEach里用jest.clearAllMocks()重置所有 mock 的调用记录和返回值 - 或者在每个
it结束后用.mockRestore()恢复原始实现(适合 spyOn 场景) - 避免在
it内部调用jest.mock()—— 它只在模块加载阶段起作用,运行时无效

















