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

Jest测试中无法Mock Webpack定义的全局变量该如何解决?

解决Jest中Mock Webpack DefinePlugin全局变量的问题

问题根源

Webpack的DefinePlugin是编译时替换变量,你的commonUtil.js在加载时就已经根据初始的__ENV__值生成了log函数。测试时直接修改__ENV__不会生效,因为log的逻辑已经在模块加载阶段固定了,后续的变量改动无法影响它。

解决方案

要覆盖不同环境的测试场景,需要确保每次测试都能重新加载commonUtil模块,并且在加载前设置好对应的全局变量。

方案1:重置模块缓存 + 预设置全局变量

利用jest.resetModules()在每个测试用例前清空模块缓存,然后在加载commonUtil前设置全局的__ENV__,这样每次测试都会基于新的变量生成log函数。

修改测试文件如下:

// commonUtil.jest.js
const envs = { PROD: 'prod', DEV: 'dev' }; // 匹配你的实际envs定义

describe('commonUtils', () => {
  const testMsg = 'test';

  beforeEach(() => {
    jest.resetModules(); // 重置模块缓存,避免复用之前加载的commonUtil
    jest.spyOn(console, 'log').mockImplementation(() => {}); // 统一Mock console.log
  });

  afterEach(() => {
    console.log.mockRestore(); // 测试后恢复console.log原始实现
  });

  it('在生产环境不输出日志', () => {
    global.__ENV__ = envs.PROD; // 加载模块前设置全局变量
    const { log } = require('./commonUtil');
    
    log(testMsg);
    expect(console.log).not.toHaveBeenCalled();
  });

  it('在开发环境输出日志', () => {
    global.__ENV__ = envs.DEV;
    const { log } = require('./commonUtil');
    
    log(testMsg);
    expect(console.log).toHaveBeenCalledWith(testMsg);
  });
});

方案2:Jest配置全局注入变量(适合固定场景)

如果只需要针对所有测试设置统一的环境变量,可以在jest.config.js中配置globals:

// jest.config.js
module.exports = {
  globals: {
    __ENV__: JSON.stringify('dev') // 注意和DefinePlugin格式一致,用JSON.stringify生成带引号的字符串
  }
};

这种方式无法在单个测试用例中切换环境,适合单一环境的测试场景。

关键注意点

  • DefinePlugin会把__ENV__替换为字符串字面量,比如配置__ENV__: 'prod',实际代码中会变成'prod',所以模拟时要赋值对应的字符串,而非变量引用。
  • 必须在加载commonUtil模块前设置全局变量,否则模块加载时已生成固定的log函数,后续修改无效。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 03:20:00