使用ts-jest+jsdom时无法Mock document.adoptedStyleSheets属性的问题
问题
在Jest + ts-jest + jsdom测试环境中,需要Mock document.adoptedStyleSheets 属性(该属性目前未被jsdom原生支持),但尝试多种方法后该属性始终为undefined,甚至无法Mock document对象上的任何自定义属性,怀疑document对象是写保护的。此前找到过非TypeScript环境下的同类解决方案,但适配到ts-jest后无效。
当前尝试的Mock代码写在beforeAll()块中:
Object.defineProperty(document, 'adoptedStyleSheets', { // 未生效的Mock逻辑 });
附上相关配置文件:
jest.config.js
/** @type {import('ts-jest').JestConfigWithTsJest} */ export default { preset: 'ts-jest', testEnvironment: 'jsdom', transform: { '^.+\\.tsx?$': ['ts-jest', { tsconfig: 'tsconfig.test.json', }] }, setupFilesAfterEnv: ['<rootDir>/jest-setup.ts'] };
jest.setup.ts
import '@testing-library/jest-dom';
tsconfig.test.json
{ "include": [ ".plasmo/index.d.ts", "./**/*.ts", "./**/*.tsx", "./jest-setup.ts" ], "compilerOptions": { "jsx": "react-jsx", "paths": { "~*": [ "./src/*" ] }, "baseUrl": ".", "esModuleInterop": true } }
解决方案
1. 正确配置Object.defineProperty参数
默认情况下,Object.defineProperty的configurable、writable、enumerable均为false,而jsdom可能已隐式定义了adoptedStyleSheets属性(值为undefined),导致无法覆盖。需显式开启可配置与可写权限,并设置Mock值:
beforeAll(() => { Object.defineProperty(document, 'adoptedStyleSheets', { value: [], // 替换为你需要的Mock对象,比如模拟的CSSStyleSheet数组 writable: true, configurable: true, enumerable: true }); });
2. 处理TypeScript类型报错
由于TypeScript的DOM类型定义中,adoptedStyleSheets通常标记为只读属性,直接修改会触发类型错误。可在jest-setup.ts中扩展全局Document类型:
declare global { interface Document { adoptedStyleSheets: CSSStyleSheet[]; } } // 确保此模块被识别为模块 export {};
3. 替代方案:使用jest.spyOn拦截getter
若adoptedStyleSheets是通过getter访问的,可直接用jest的spyOn方法Mock其getter:
beforeAll(() => { jest.spyOn(document, 'adoptedStyleSheets', 'get').mockReturnValue([]); });
4. 确保Mock执行时机
确认Mock代码在测试逻辑之前执行:
- 可将Mock代码放在
beforeAll或beforeEach中 - 也可将全局Mock逻辑放在
jest-setup.ts中,确保所有测试用例启动前已生效
内容的提问来源于stack exchange,提问作者Marten
相关产品推荐
相关产品推荐

