You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Jest中为单个测试用例单独mock原始类型的变量值

问题原因

Jest 只会对写在测试文件顶层的jest.mock执行静态提升,写在测试用例函数内部的jest.mock不会被提升,会在运行时才执行。但此时你的测试文件已经在顶部导入过myapp-api-functions或依赖该模块的业务代码,Node.js的模块缓存机制会保留第一次导入的模块实例,后续的mock不会更新已经加载的模块,因此出现mock不生效的问题。而把jest.mock写在顶层时会在所有模块导入前执行,所以可以生效,但会全局修改模块值影响其他测试用例。

解决方案

方案1:使用jest.spyOn动态覆写导出值(更推荐)

这种方案不需要调整模块导入逻辑,性能更好:

  1. 首先在测试文件顶部正常导入目标模块:
import * as myAppApi from 'myapp-api-functions';
  1. 在需要修改isBanana的单测内临时覆写值,测试结束后恢复原始值:
it(`should error when someone tries to use the mock account in production`, async () => {
  // 覆写isBanana的返回值为false
  const bananaSpy = jest.spyOn(myAppApi, 'isBanana', 'get').mockReturnValue(false);

  // 原有的测试逻辑
  // ...

  // 恢复原始值,避免影响其他测试用例
  bananaSpy.mockRestore();
});

注:ES模块的常量导出默认会被封装为getter,因此加上第三个参数'get'即可正确覆写原始类型的导出值。

方案2:使用jest.doMock运行时mock

如果需要更彻底的模块隔离,可以用不会被提升的jest.doMock,配合重置模块缓存实现单用例mock:

it(`should error when someone tries to use the mock account in production`, async () => {
  // 运行时mock模块,不会被提升
  jest.doMock("myapp-api-functions", () => {
    console.log(`executing mock function`);
    return {
      ...jest.requireActual("myapp-api-functions"),
      isBanana: false,
    };
  });

  // 必须重新导入模块,清除之前的缓存
  const myAppApi = require('myapp-api-functions');
  // 如果有依赖该模块的业务代码,也需要重新导入
  // const businessModule = require('./your-business-code');

  // 原有的测试逻辑
  // ...

  // 测试结束后重置模块缓存,避免影响其他用例
  jest.resetModules();
});

内容的提问来源于stack exchange,提问作者mikemaccana

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.05 05:15:01