You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

setupFilesAfterEnv中的Jest对象与测试文件中的Jest对象引用不一致问题

setupFilesAfterEnv中的Jest对象与测试文件中的Jest对象引用不一致问题

这个坑我之前踩过!当时盯着控制台的undefinedfalse愣了好久,后来才搞懂是Jest的上下文隔离机制在搞鬼,给你唠唠问题根源和解决办法:

问题根源

Jest为了保证每个测试用例的环境独立性,会在setupFilesAfterEnv的初始化上下文单个测试文件的执行上下文中生成完全不同的jest对象实例。你在setup文件里修改的是初始化阶段的临时实例,而测试文件里用到的是Jest单独注入的全新实例,二者引用完全不重合,所以你挂载的toto属性自然在测试里读不到。

就像你代码里的情况:setup里把当前jest存到global.jestCopy,测试里对比发现jestCopy !== jest,本质就是两个完全不同的对象。

解决办法

方法一:直接挂载到全局对象(简单粗暴)

既然两个jest实例不共享,那我们直接把自定义属性挂到globalThis(Node环境下也可以用global)上,这样测试文件就能直接访问了:

// test/config.ts(setup文件)
// 方式1:直接挂全局
(globalThis as any).toto = 'toto';

// 方式2:如果你想挂在jest名下,也可以这样
(globalThis as any).jest.toto = 'toto';

然后在测试文件里:

// *.spec.ts
console.log(globalThis.toto); // 输出 'toto'
// 或者用你想要的方式
console.log(jest.toto); // 输出 'toto'

要是用TypeScript的话,别忘了扩展全局类型避免报错,新建一个types/jest.d.ts文件:

declare global {
  var toto: string;
  namespace jest {
    interface Jest {
      toto: string;
    }
  }
}
export {};

然后在tsconfig.json里把这个类型文件加入include列表:

{
  "include": ["src/**/*", "types/**/*"]
}

方法二:从@jest/globals获取一致的Jest实例

测试文件里的jest其实是从@jest/globals模块导入的,你在setup文件里也直接导入这个模块的jest实例,修改它的属性,这样测试文件里就能读到了:

// test/config.ts
import { jest as globalJest } from '@jest/globals';
(globalJest as any).toto = 'toto';

测试文件里直接用就行:

// *.spec.ts
console.log(jest.toto); // 输出 'toto'

同样要加上面提到的TypeScript类型扩展,不然TS会报属性不存在的错误。

方法三:利用Jest的全局配置共享

如果你想更贴合Jest的规范,可以把自定义属性挂到Jest的全局配置上:

// test/config.ts
jest.config.global.toto = 'toto';

测试文件里通过配置对象访问:

// *.spec.ts
console.log(jest.config.global.toto); // 输出 'toto'

总结

核心就是绕开Jest的上下文隔离,要么通过全局对象共享属性,要么直接操作测试文件会用到的那个jest实例。记得给TypeScript补全类型,不然写代码的时候会红报错,影响开发体验~

火山引擎 最新活动