为何无法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
相关产品推荐
相关产品推荐

