JavaScript单元测试中Mock的核心目标是隔离被测class的依赖,控制其行为并验证交互;需mock依赖模块、方法或实例属性,而非class自身,避免污染和绕过逻辑。

JavaScript 中对 class 进行单元测试时,Mock 的核心目标是:隔离被测 class 的依赖(如外部 API、其他类、定时器、DOM 操作等),控制其行为,验证它如何与这些依赖交互。不 mock class 本身,而是 mock 它所依赖的模块、方法或实例属性。
Mock 类的依赖方法(最常见场景)
当一个 class 内部调用外部函数或另一个 class 的方法时,推荐在测试前用 jest.mock() 或 jest.spyOn() 替换它。
- 用
jest.mock('./utils')自动 mock 整个模块,再通过mockImplementation定义返回值 - 若只 mock 某个方法(比如 class 里用了
Date.now()),可用jest.spyOn(Date, 'now').mockReturnValue(123456789) - 对第三方库(如
axios),常 mock 其get、post方法并返回 Promise:axios.get.mockResolvedValue({ data: { id: 1 } })
Mock 类的实例方法(用于测试内部逻辑分支)
如果想测试某个 class 实例方法是否被正确调用(比如私有辅助方法),可在创建实例后,用 jest.spyOn(instance, 'methodName')。
- 注意:必须在实例化之后 spy,否则会报 “Cannot spy the method because it does not exist”
- 可配合
.mockImplementation()改变行为,或用.mockReturnValue()控制返回结果 - 例如:
const inst = new UserService(); jest.spyOn(inst, 'fetchUser').mockResolvedValue({ name: 'Alice' })
Mock 构造函数或 new 行为(控制 new 出来的对象)
当 class 内部通过 new SomeService() 创建依赖实例时,需要 mock 构造函数本身。
立即学习“Java免费学习笔记(深入)”;
- 用
jest.mock('./SomeService')后,Jest 会自动生成一个 mock 构造函数 - 可通过
SomeService.mockImplementation(() => ({ doWork: jest.fn() }))定义实例行为 - 也可用
SomeService.mockReturnValue({ doWork: jest.fn() })直接指定 new 返回的对象 - 验证是否被 new:用
expect(SomeService).toHaveBeenCalledTimes(1)
避免常见误区
Mock 不是为了“绕过逻辑”,而是为了明确边界、提升测试稳定性和可读性。
- 不要 mock 被测 class 自身的 public 方法来“让测试通过”——这等于没测真实逻辑
- 不要在测试中修改 class 原型(如
User.prototype.save = jest.fn()),容易污染其他测试 - 每个 test 用
afterEach(() => jest.clearAllMocks())重置 mock 状态,防止状态泄漏 - 构造函数里执行副作用(如发请求、改全局状态)不利于测试,建议把初始化逻辑抽到单独方法中,便于 mock 或跳过


















