如何在 Jest 测试运行时给全局对象动态添加字段并持久化

作者:袖梨 2026-07-11

Jest 的 global setup/teardown 作用域隔离导致测试中对 global 对象的修改无法在 teardown 阶段访问;正确做法是将全局状态封装为可变对象(如配置对象),挂载到 global 上,再通过引用修改其属性。

jest 的 global setup/teardown 作用域隔离导致测试中对 `global` 对象的修改无法在 teardown 阶段访问;正确做法是将全局状态封装为可变对象(如配置对象),挂载到 `global` 上,再通过引用修改其属性。

在 Jest 中,global-setup.ts 和 global-teardown.ts 确实各执行一次,但 Jest 会在每个测试文件(甚至每个测试用例)运行前克隆或重置 global 对象的部分状态——尤其是直接挂载在 global 上的原始值(如 global.sometwo = 2)不会跨测试生命周期保留,因此 global-teardown 中读取不到测试中新增的顶层属性。

根本原因在于:Jest 的测试沙箱机制默认不保证 global 对象的跨测试可变性,直接赋值的原始类型字段(string、number、boolean)会被隔离,而对象引用则可被共享修改。

✅ 正确实践:将全局状态统一托管为一个可变对象(如 global.testConfig),所有动态字段均作为该对象的属性操作:

// testConfig.jsmodule.exports = {  someone: 1,};
// global-setup.tsconst testConfig = require('./testConfig');module.exports = async (config, projectConfig) => {  // 挂载整个配置对象(引用传递)  global.testConfig = testConfig;};
// testfile.test.tsdescribe('sometitle', () => {  test('testTitle', () => {    try {      console.log(global.testConfig.someone); // ✅ 输出 1      expect(false).toBe(true);    } catch (e) {      // ✅ 修改对象属性(非重新赋值 global.xxx)      global.testConfig.sometwo = 2;      throw e;    }  });});
// global-teardown.tsmodule.exports = async (globalConfig, projectConfig) => {  console.log(global.testConfig.someone); // ✅ 1  console.log(global.testConfig.sometwo); // ✅ 2 —— 此处可正常访问};

⚠️ 注意事项:

  • ❌ 避免 global.newField = value(原始值赋值),因其不可跨测试持久化;
  • ✅ 始终通过 global.existingObject.newProp = value 方式扩展;
  • 若需多测试间共享状态,建议额外结合 jest-worker 或临时文件,但应谨慎使用(影响测试隔离性);
  • TypeScript 用户请为 global 添加类型声明(如 declare global { var testConfig: Record<string, any>; }),确保类型安全。

该方案兼顾 Jest 的设计约束与实际调试/状态跟踪需求,是符合测试最佳实践的稳健解法。

相关文章

精彩推荐