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

为何无法Mock重新导出的原始值?测试失败原因探究

问题

在测试中修改配置对象的值时发现:当依赖配置值的导出被包裹在函数中时,Mock和断言正常工作;但直接导出原始值时,Mock无效,值为undefined。以下是简化示例:

代码示例

config.ts

export const config = {
  environment: 'test'
};

app.ts

import { config } from './config';

export const app = () => config.environment;

export const environment = config.environment;

app.spec.ts

import { app, environment } from './app';
import * as config from './config';

jest.mock('./config', () => ({
  config: {},
}));

beforeEach(() => {
  jest.resetAllMocks();
});

const mockConfig = config.config as jest.Mocked<typeof config.config>;

test('app', () => {
  mockConfig.environment = 'prod';
  expect(app()).toEqual('prod');
});

test('environment', () => {
  mockConfig.environment = 'nonprod';
  expect(environment).toEqual('nonprod');
});

测试失败信息

第一个测试通过,但第二个测试environment失败,报错如下:

✕ environment (3 ms)

  ● environment

    expect(received).toEqual(expected) // deep equality

    Expected: "nonprod"
    Received: undefined

      19 | test('environment', () => {
      20 |   mockConfig.environment = 'nonprod';
    > 21 |   expect(environment).toEqual('nonprod');
         |                             ^
      22 | });
      23 |

      at Object.<anonymous> (config/app.spec.ts:21:29)

原因分析

这是模块加载与变量初始化时机导致的:

  • Jest Mock的执行优先级:jest.mock会在所有模块导入语句执行前运行,所以当app.ts被导入时,它依赖的config已经是你定义的Mock空对象{}。
  • 直接导出变量的特性:app.ts里的export const environment = config.environment是在模块初始化阶段完成赋值的——此时Mock的config没有environment属性,值为undefined,这个值会被永久固定,后续修改mockConfig.environment不会改变已经初始化好的environment变量。
  • 函数导出的动态性:app()函数是在测试用例执行时才被调用,每次调用都会重新读取config.environment的当前值,所以你在测试中修改Mock值后,函数能拿到最新的结果。

直白点说:直接导出的变量是模块加载时拍的"静态快照",函数则是每次调用时的"动态读取"。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 05:01:11