Jest模拟第三方模块需在import前调用jest.mock(),分自动、手动、内联三种策略,异步模块须mockResolvedValue/mockRejectedValue,验证应聚焦调用细节而非仅返回值。

在 JS 单元测试中用 Jest 模拟第三方模块,核心是控制依赖的输入输出,让测试只关注被测代码逻辑本身。关键不在于“能不能 mock”,而在于“什么时候 mock、怎么 mock、怎么验证”。
必须在 import 前调用 jest.mock()
Jest 的模块模拟机制会在模块解析阶段生效,如果 jest.mock('axios') 写在 import axios from 'axios' 之后,实际导入的仍是原始模块,mock 就失效了。
- 正确写法:测试文件顶部第一行(或至少在所有相关 import 之前)调用 jest.mock('xxx')
- 常见错误:把 mock 放在 test 块里、或放在 import 下方、或用条件判断包裹
- 补充技巧:需要还原模块状态时,可用 jest.resetModules() 清除缓存,再重新 import
三种常用模拟策略选对场景
自动模拟适合快速隔离、手动模拟适合定制行为、内联模拟适合轻量临时覆盖。
DMap GL地图JSAPI(dmapgl)开发指南。用于编写、审查、调试 DMap 地图 API 代码,涵盖地图初始化、覆盖物渲染、图层管理、事件处理、控件交互等任务。当用户提及 dmap、dmapgl、jsapi‑gl 或相关地图开发需求时自动触发。
- 自动模拟:只写 jest.mock('fs'),Jest 会自动生成空壳——所有方法变 mock 函数,返回 undefined 或 Promise.resolve(),适合只需断言是否被调用的场景
- 手动模拟:在 __mocks__/fs.js 中导出你定义的对象,比如 readFileSync: jest.fn().mockReturnValue('test content'),适合需要固定返回值或复杂结构的模块
- 内联模拟:直接传工厂函数,如 jest.mock('path', () => ({ join: jest.fn().mockReturnValue('/a/b') })),适合单个测试中特殊定制,不污染其他用例
异步模块(如 axios)要处理 Promise 分支
第三方模块常含异步操作,mock 必须明确 resolve 或 reject,否则测试会超时或逻辑跳过。
- 成功路径:用 mockResolvedValue({ data: { id: 1 } }) 模拟正常响应
- 失败路径:用 mockRejectedValue(new Error('Network error')) 触发 catch 分支
- 注意:axios.get.mockResolvedValue(...) 必须在 jest.mock('axios') 之后、实际调用前设置,且不能在 mock 工厂函数里引用外部变量(会报 out-of-scope 错误)
验证调用细节比只看返回值更重要
模拟的目的不是让测试“跑通”,而是确认被测代码是否按预期与依赖交互。
- 检查是否调用:expect(axios.get).toHaveBeenCalled()
- 检查参数是否正确:expect(axios.get).toHaveBeenCalledWith('/users/123')
- 检查调用次数:expect(fs.writeFileSync).toHaveBeenCalledTimes(1)
- 检查返回值类型或结构(配合 toEqual):expect(result).toEqual({ id: 1, name: 'test' })

















