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 —— 此处可正常访问};
⚠️ 注意事项:
该方案兼顾 Jest 的设计约束与实际调试/状态跟踪需求,是符合测试最佳实践的稳健解法。