基础函数模拟
使用 [mock] 函数创建模拟。Jest 兼容性
另外,您可以使用 Jest 中的 [jest.fn()] 函数。它的行为完全相同。模拟函数属性
[mock()] 的结果是一个被添加了一些额外属性的新函数。可用属性和方法
以下属性和方法在模拟函数上实现:| 属性/方法 | 描述 |
|---|---|
| [mockFn.getMockName()] | 返回模拟名称 |
| [mockFn.mock.calls] | 每次调用的参数数组 |
| [mockFn.mock.results] | 每次调用的返回值数组 |
| [mockFn.mock.instances] | 每次调用的 this 上下文数组 |
| [mockFn.mock.contexts] | 每次调用的 this 上下文数组 |
| [mockFn.mock.lastCall] | 最近一次调用的参数 |
| [mockFn.mockClear()] | 清除调用历史 |
| [mockFn.mockReset()] | 清除调用历史并删除实现 |
| [mockFn.mockRestore()] | 恢复原始实现 |
| [mockFn.mockImplementation(fn)] | 设置新实现 |
| [mockFn.mockImplementationOnce(fn)] | 仅为下次调用设置实现 |
| [mockFn.mockName(name)] | 设置模拟名称 |
| [mockFn.mockReturnThis()] | 设置返回值为 this |
| [mockFn.mockReturnValue(value)] | 设置返回值 |
| [mockFn.mockReturnValueOnce(value)] | 仅为下次调用设置返回值 |
| [mockFn.mockResolvedValue(value)] | 设置解析的 Promise 值 |
| [mockFn.mockResolvedValueOnce(value)] | 仅为下次调用设置解析的 Promise |
| [mockFn.mockRejectedValue(value)] | 设置拒绝的 Promise 值 |
| [mockFn.mockRejectedValueOnce(value)] | 仅为下次调用设置拒绝的 Promise |
| [mockFn.withImplementation(fn, callback)] | 临时更改实现 |
实际示例
基础模拟用法
动态模拟实现
异步模拟
使用 spyOn() 创建间谍
可以跟踪函数调用而不将其替换为模拟。使用 [spyOn()] 创建间谍;这些间谍可以传递给 [.toHaveBeenCalled()] 和 [.toHaveBeenCalledTimes()]。高级间谍用法
使用 mock.module() 模拟模块
模块模拟允许您覆盖模块的行为。使用mock.module(path: string, callback: () => Object) 来模拟模块。
覆盖已导入的模块
如果您需要覆盖已导入的模块,无需特殊操作。只需调用mock.module(),模块就会被覆盖。
提升和预加载
如果您需要确保模块在导入前被模拟,应使用--preload 在测试运行前加载您的模拟。
terminal
bunfig.toml
模块模拟最佳实践
何时使用预加载
如果我模拟一个已经被导入的模块会发生什么? 如果您模拟一个已被导入的模块,该模块将在模块缓存中被更新。这意味着任何导入该模块的模块将获得模拟版本,但是原始模块仍会被评估。这意味着原始模块的所有副作用仍将发生。 如果您想阻止原始模块被评估,应使用--preload 在测试运行前加载您的模拟。
实际模块模拟示例
模拟外部依赖
全局模拟函数
清除所有模拟
重置所有模拟函数状态(调用、结果等),但不恢复其原始实现:恢复所有模拟
与其单独使用 [mockFn.mockRestore()] 恢复每个模拟,不如通过调用 [mock.restore()] 用一条命令恢复所有模拟。这样做不会重置使用mock.module() 覆盖的模块的值。
Vitest 兼容性
为了增强针对 Vitest 编写的测试的兼容性,Bun 提供了 [vi] 对象作为 Jest 模拟 API 部分功能的别名:实现细节
了解mock.module() 如何工作有助于您更有效地使用它:
缓存交互
模块模拟与 ESM 和 CommonJS 模块缓存交互。惰性评估
只有在实际导入或需要模块时才会评估模拟工厂回调。路径解析
Bun 自动解析模块说明符,就像您在做导入一样,支持:- 相对路径 (
'./module') - 绝对路径 (
'/path/to/module') - 包名 (
'lodash')
导入时机效果
- 在首次导入前模拟:原始模块不会产生副作用
- 在导入后模拟:原始模块的副作用已经发生
--preload。
活跃绑定
模拟的 ESM 模块保持活跃绑定,因此更改模拟将更新所有现有导入。高级模式
工厂函数
条件模拟
模拟清理模式
最佳实践
保持模拟简单
使用类型安全的模拟
测试模拟行为
注意事项
自动模拟
__mocks__ 目录和自动模拟尚未支持。如果这阻碍您切换到 Bun,请 提交问题。