首页 > web前端 > js教程 > 正文

在 Jest 中灵活切换手动 Mock 与实际模块实现

花韻仙語
发布: 2025-10-29 13:57:01
原创
565人浏览过

在 Jest 中灵活切换手动 Mock 与实际模块实现

本文深入探讨了在 jest 测试框架中,如何有效管理手动模拟(manual mock)与实际模块的切换使用。通过详细介绍 `jest.dontmock()` 和 `jest.resetmodules()` 这两个关键 api,文章提供了在特定测试场景下绕过全局手动模拟、调用真实模块实现的实用方法,并辅以代码示例和注意事项,旨在帮助开发者实现更灵活、精准的测试控制。

理解 Jest 模块模拟与缓存机制

在 Jest 中,当我们为某个模块(例如 axios)创建了手动模拟文件(如 __mocks__/axios.js),Jest 会在测试运行时自动使用这个模拟版本,而不是实际的 axios 包。这种机制在大多数情况下非常方便,它允许我们隔离外部依赖,专注于测试当前模块的逻辑。

然而,有时我们可能需要在同一个测试套件中,针对某些特定测试用例调用模块的真实实现。例如,在集成测试或端到端测试中,我们可能希望 axios 真正地发出 HTTP 请求。直接在测试内部使用 jest.mock("axios", () => jest.requireActual("axios")) 尝试覆盖模拟可能不会立即生效,这是因为 Jest 有一个模块注册表缓存机制。一旦模块被加载并模拟,其模拟版本就会被缓存起来,后续的 require 或 import 语句会直接从缓存中获取,而不会重新解析或应用新的模拟指令。

解决方案:jest.dontMock() 与 jest.resetModules()

为了在特定测试中绕过手动模拟并加载真实模块,我们需要结合使用 jest.dontMock(moduleName) 和 jest.resetModules()。

  1. jest.dontMock(moduleName): 这个 API 告诉 Jest 不要模拟指定的模块。它会阻止 Jest 使用 __mocks__ 目录下的手动模拟文件,而是加载模块的实际实现。

  2. jest.resetModules(): 这个 API 用于重置 Jest 的模块注册表缓存。它会清除所有已加载模块的缓存,确保下一次 require 或 import 操作会重新加载模块,从而使得 jest.dontMock() 的效果得以应用。

重要提示: jest.resetModules() 必须在 jest.dontMock() 之前调用,或者至少在模块被 import 之前调用,以确保模块注册表被清除,并且 jest.dontMock() 能够影响到后续的模块加载行为。通常,我们会在 beforeEach 钩子中调用 jest.resetModules(),以确保每个测试用例都在一个“干净”的模块环境中运行。

实践示例

下面通过一个具体的例子来演示如何实现手动模拟与实际模块的切换。

假设我们有一个 axios 的手动模拟,它总是返回一个固定的假数据:

__mocks__/axios.js:

let mockAxios = jest.genMockFromModule('axios');

// 为 get 方法提供一个默认的模拟实现
mockAxios.get = jest.fn().mockResolvedValue({ data: 'fake' });

export default mockAxios;
登录后复制

接着,我们有一个业务逻辑模块 main.ts,它使用了 axios 发送 HTTP 请求:

ViiTor实时翻译
ViiTor实时翻译

AI实时多语言翻译专家!强大的语音识别、AR翻译功能。

ViiTor实时翻译116
查看详情 ViiTor实时翻译

main.ts:

import axios from 'axios';

export function main() {
  return axios.get('https://jsonplaceholder.typicode.com/todos/1');
}
登录后复制

现在,我们编写测试文件 main.test.ts,其中包含一个使用模拟 axios 的测试和一个使用真实 axios 的测试:

main.test.ts:

describe('Axios 模块模拟与真实实现切换', () => {
  // 在每个测试用例运行前重置模块注册表
  // 这一步至关重要,它清除了之前测试可能留下的模块缓存,
  // 确保每个测试用例都能根据其自身的模拟配置加载模块。
  beforeEach(() => {
    jest.resetModules();
  });

  test('应该使用模拟的 axios', async () => {
    // 默认情况下,如果存在手动模拟,Jest 会使用它。
    // 在此测试中,我们不需要额外的 dontMock,因为我们希望使用模拟。
    const { main } = await import('./main'); // 导入 main 模块,此时 axios 会被模拟
    const actual = await main();
    console.log('使用模拟 axios 的结果:', actual?.data);
    expect(actual?.data).toEqual('fake'); // 预期返回模拟数据
  });

  test('应该使用真实的 axios', async () => {
    // 在这个测试用例中,我们明确告诉 Jest 不要模拟 axios
    jest.dontMock('axios');

    // 再次导入 main 模块。由于 resetModules 和 dontMock 的作用,
    // 此时 main 内部的 axios 将是真实实现。
    const { main } = await import('./main'); 
    const actual = await main();
    console.log('使用真实 axios 的结果:', actual?.data);
    // 预期返回真实 API 的数据结构
    expect(actual?.data).toHaveProperty('userId');
    expect(actual?.data).toHaveProperty('id');
    expect(actual?.data).toHaveProperty('title');
    expect(actual?.data).toHaveProperty('completed');
  });
});
登录后复制

运行上述测试,你将观察到以下输出:

  console.log
    使用模拟 axios 的结果: fake

  console.log
    使用真实 axios 的结果: { userId: 1, id: 1, title: 'delectus aut autem', completed: false }
登录后复制

这清楚地表明,第一个测试用例成功使用了手动模拟的 axios,而第二个测试用例通过 jest.dontMock('axios') 和 jest.resetModules() 成功加载并使用了真实的 axios 模块,并从外部 API 获取了数据。

注意事项与最佳实践

  • jest.resetModules() 的位置: 最好将其放在 beforeEach 钩子中,以确保每个测试用例都从一个干净的模块状态开始。这可以避免测试之间的状态泄露,提高测试的独立性和可靠性。
  • 性能考量: jest.resetModules() 会清除模块缓存并重新加载所有模块,这可能会对测试运行时间产生轻微影响,尤其是在大型项目中。然而,对于大多数单元和集成测试场景,这种开销通常是可接受的,并且其带来的测试隔离性收益远大于性能损失。
  • 局部模拟: 如果你只是想在某个测试文件中对某个模块进行临时模拟,而不是全局手动模拟,可以使用 jest.doMock() 结合 jest.unmock()。但对于本文讨论的“绕过已存在的手动模拟”场景,jest.dontMock() 是更直接的方案。
  • jest.requireActual() 的替代用途: jest.requireActual(moduleName) 通常用于在模拟文件中获取模块的真实实现,以便在模拟中部分地使用真实逻辑。例如:const actualAxios = jest.requireActual('axios'); mockAxios.post = actualAxios.post;。这与本文讨论的在测试中完全禁用模拟是不同的场景。

总结

通过熟练运用 jest.dontMock() 和 jest.resetModules(),开发者可以在 Jest 测试中获得对模块模拟行为的精细控制。这使得在同一个测试套件中,既能利用手动模拟进行隔离测试,又能按需调用真实模块进行更接近生产环境的集成测试,从而极大地提升了测试的灵活性和覆盖范围。理解并正确使用这些 Jest API 是编写健壮、可维护测试的关键。

以上就是在 Jest 中灵活切换手动 Mock 与实际模块实现的详细内容,更多请关注php中文网其它相关文章!

最佳 Windows 性能的顶级免费优化软件
最佳 Windows 性能的顶级免费优化软件

每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。

下载
来源:php中文网
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新问题
开源免费商场系统广告
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习
PHP中文网抖音号
发现有趣的

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号