es modules 的 mock 必须基于 import 语法和模块机制设计,vi.mock 或 jest.mock 需在 import 后(vitest)或前(jest)顶层声明,require 会绕过拦截导致 mock 失效;必须统一使用 import 语法、.js 后缀及 "type": "module",并确保 mock 路径与 import 路径完全一致。

ES Modules 的 mock 在单元测试中必须基于模块导入机制本身来设计,不能靠运行时替换变量。核心前提是:所有被 mock 的模块必须用 import 语法引入,且 vi.mock 或 jest.mock 必须在 import 之前调用(Jest 静态提升、Vitest 要求顶层声明)。
确保使用 ES Modules 语法
CommonJS 的 require() 会绕过 Vitest/Jest 的模块拦截机制,导致 vi.mock 或 jest.mock 完全失效。必须统一改为:
-
import { something } from './module.js'(推荐带 .js 后缀,避免 Node 解析歧义) - 移除所有
const mod = require('./module')写法 - 确认 package.json 中已设置
"type": "module"或测试文件以.mjs结尾
用 vi.mock(Vitest)或 jest.mock(Jest)替换模块导出
不是 mock “某个值”,而是 mock 整个模块的默认/具名导出。例如:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- Vitest 写法(需放在 import 之后、test 之前,但仍在顶层):
vi.mock('./apiClient', () => ({<br> ApiClient: class { fetch() { return Promise.resolve({ ok: true }); } }<br>})); - Jest 写法(支持静态提升,可放 import 前):
jest.mock('./apiClient', () => ({<br> ApiClient: jest.fn().mockImplementation(() => ({ fetch: jest.fn().mockResolvedValue({}) }))<br>}));
按需控制返回行为:实例、方法、属性
mock 模块后,重点是让 new 实例或函数调用返回可控对象:
- 构造函数场景:用
mockImplementation返回带 stub 方法的对象,如{ fetch: jest.fn().mockResolvedValue(data) } - 函数导出场景:直接 mock 函数行为,如
fetchUser: jest.fn().mockResolvedValue({ id: 1 }) - 需要多次不同响应?用
mockImplementationOnce链式设置
注意模块路径与解析一致性
mock 路径必须和 import 路径完全一致(包括相对路径写法、是否含 .js)。常见坑:
- 源码 import './utils',但 mock 写成 './utils/index.js' → 不生效
- Vite 项目中 alias 别名(如 @/api)在测试中未配置,mock 时仍要用真实路径
- TypeScript 的路径映射(paths)不会被 Jest/Vitest 自动识别,mock 时需用实际文件路径
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










