
本文详细阐述了在 Jest 测试框架中,当存在模块的手动 Mock 实现时,如何在特定测试用例或测试套件中选择性地使用模块的真实实现。核心解决方案是结合使用 jest.dontMock(moduleName) 和 jest.resetModules(),以确保测试环境的灵活性和准确性。
在 Jest 中进行单元测试时,我们经常会为外部依赖(如网络请求库 Axios、数据库连接等)创建手动 Mock (__mocks__/moduleName.js)。这种方式能有效地隔离被测模块,使测试聚焦于其自身逻辑,避免真实依赖带来的副作用或性能开销。
然而,在某些场景下,我们可能需要验证模块与真实依赖的集成情况,或者在同一个测试文件中,某些测试用例需要 Mock,而另一些则需要真实的模块实现。直接在测试用例内部使用 jest.mock("moduleName", () => jest.requireActual("moduleName")) 往往无法达到预期效果,因为 Jest 的模块加载机制在测试执行前就已经处理了手动 Mock,后续的 jest.mock 调用可能无法覆盖已缓存的 Mock。
要实现动态切换,我们需要结合使用 Jest 提供的两个关键 API:
通过在测试用例或 beforeEach 钩子中先调用 jest.resetModules() 清除模块缓存,再调用 jest.dontMock('moduleName'),可以确保当模块被重新导入时,Jest 会加载其真实实现而非 Mock。
以下通过一个使用 axios 的具体例子,演示如何在一个测试套件中同时测试 Mocked axios 和真实 axios 的行为。
首先,创建一个 axios 的手动 Mock。这个 Mock 会拦截 axios.get 调用并返回一个预设的假数据。
// __mocks__/axios.js
let mockAxios = jest.genMockFromModule('axios');
// 为 get 方法提供一个 Mock 实现
mockAxios.get = jest.fn().mockResolvedValue({ data: 'fake' });
export default mockAxios;这是一个简单的模块,它使用 axios 发起一个 GET 请求。
// main.ts
import axios from 'axios';
export function main() {
return axios.get('https://jsonplaceholder.typicode.com/todos/1');
}在这个测试文件中,我们将编写两个测试用例:一个使用 Mocked axios,另一个使用真实的 axios。
// main.test.ts
import { main } from './main'; // 导入被测试的模块
describe('Axios 模块切换测试', () => {
// 在每个测试用例运行前重置模块缓存
beforeEach(() => {
jest.resetModules();
});
test('应该使用 Mocked Axios', async () => {
// 默认情况下,如果存在手动 Mock,Jest 会使用它
const result = await main();
expect(result.data).toEqual('fake'); // 验证是否返回 Mock 数据
console.log('Mocked Axios 结果:', result.data);
});
test('应该使用真实的 Axios', async () => {
// 在这个测试用例中,我们取消对 axios 的 Mock
jest.dontMock('axios');
// 由于 beforeEach 中已经 resetModules,这里重新导入 main 模块
// 此时 main 模块内部引用的 axios 将是真实的 axios
const { main: actualMain } = await import('./main');
const result = await actualMain();
// 验证是否返回真实数据(通常是来自 API 的 JSON 对象)
expect(result).toHaveProperty('data');
expect(result.data).toHaveProperty('userId');
expect(result.data).toHaveProperty('id');
console.log('真实 Axios 结果:', result.data);
});
});运行上述测试后,你将看到类似以下的输出:
console.log
Mocked Axios 结果: fake
console.log
真实 Axios 结果: { userId: 1, id: 1, title: 'delectus aut autem', completed: false }
PASS ./main.test.ts
Axios 模块切换测试
✓ 应该使用 Mocked Axios (XX ms)
✓ 应该使用真实的 Axios (YY ms)
Test Suites: 1 passed, 1 total
Tests: 2 passed, 2 total
Snapshots: 0 total
Time: ZZ s从输出可以看出,第一个测试用例成功地使用了手动 Mock 返回了 'fake' 数据,而第二个测试用例则成功地发起了真实的网络请求,并从 jsonplaceholder.typicode.com 获取了真实的数据。这证明了 jest.dontMock 和 jest.resetModules 组合的有效性。
在 Jest 测试中,通过巧妙地结合使用 jest.dontMock(moduleName) 和 jest.resetModules(),我们可以实现对模块 Mock 行为的精细控制。这种方法允许开发者在同一测试套件中灵活地切换使用模块的 Mock 实现或真实实现,从而满足更复杂的测试需求,确保测试的全面性和准确性。理解并掌握这一技巧,将极大地提升 Jest 测试的灵活性和效率。
以上就是Jest 测试中动态切换手动 Mock 与真实模块实现的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号