使用import.meta导致Jest测试失败(React+TypeScript+Vite环境)
解决Jest中.ts文件import.meta.env未定义的问题
针对你的场景——ts-jest-mock-import-meta仅解决了.tsx文件的import.meta问题,但.ts文件仍报错,以下是几种可行的解决方案:
方案1:修复ts-jest-mock-import-meta的配置覆盖问题
你的transform规则^.+\\.tsx?$理论上覆盖.ts和.tsx文件,但项目启用ESM(package.json中type: "module")可能导致ts-jest对.ts文件的转换逻辑异常,可按以下方式调整:
调整为CommonJS风格配置(兼容性更好)
移除jest.config.ts中的type: 'module',改用CommonJS导出:
module.exports = { preset: 'ts-jest', testEnvironment: 'jest-environment-jsdom', transform: { '^.+\\.tsx?$': [ 'ts-jest', { diagnostics: { ignoreCodes: [1343], }, astTransformers: { before: [ { path: 'ts-jest-mock-import-meta', options: { metaObjectReplacement: { API_ENDPOINT: 'https://www.url.com', API_URL: 'https://www.url.com', // 补充代码中用到的API_URL test2: 'test2', test3: 'test3', }, }, }, ], }, }, ], }, moduleNameMapper: { '\\.(gif|ttf|eot|svg|png)$': '<rootDir>/src/test/__mocks__/fileMock.js', '\\.(css|less)$': '<rootDir>/src/test/__mocks__/styleMock.js', }, setupFiles: ['<rootDir>/jest.setup.ts'], };
保留ESM配置的适配
若必须使用ESM,添加ESM相关配置项:
export default { preset: 'ts-jest', testEnvironment: 'jest-environment-jsdom', extensionsToTreatAsEsm: ['.ts', '.tsx'], moduleNameMapper: { '^(\\.{1,2}/.*)\\.js$': '$1', '\\.(gif|ttf|eot|svg|png)$': '<rootDir>/src/test/__mocks__/fileMock.js', '\\.(css|less)$': '<rootDir>/src/test/__mocks__/styleMock.js', }, transform: { '^.+\\.tsx?$': [ 'ts-jest', { useESM: true, diagnostics: { ignoreCodes: [1343], }, astTransformers: { before: [ { path: 'ts-jest-mock-import-meta', options: { metaObjectReplacement: { API_ENDPOINT: 'https://www.url.com', API_URL: 'https://www.url.com', test2: 'test2', test3: 'test3', }, }, }, ], }, }, ], }, setupFiles: ['<rootDir>/jest.setup.ts'], };
方案2:全局模拟import.meta.env(简单直接)
跳过第三方库,直接在jest初始化阶段全局模拟import.meta.env,对.ts和.tsx文件均生效:
- 在
jest.setup.ts中添加模拟代码:
// 全局模拟import.meta.env Object.defineProperty(globalThis, 'import.meta', { value: { env: { API_ENDPOINT: 'https://www.url.com', API_URL: 'https://www.url.com', // 按需添加其他环境变量 }, }, });
- 为TypeScript添加类型声明,创建
src/types/global.d.ts:
declare global { interface ImportMeta { env: { API_ENDPOINT?: string; API_URL?: string; // 定义所有用到的环境变量类型 }; } } export {};
适配条件调用场景
这种方式完全兼容你条件使用环境变量的代码:
const apiURL = import.meta.env.API_URL ? `${import.meta.env.API_URL}` : "http://localhost:8080"
若需要测试API_URL为undefined的场景,可在单测文件中单独覆盖:
beforeEach(() => { (globalThis.import.meta.env as any).API_URL = undefined; }); test('API_URL未定义时使用默认地址', () => { // 执行测试逻辑 });
方案3:自定义AST转换器(灵活可控)
编写自定义ts-jest转换器,精准替换import.meta.env引用:
- 创建
src/test/transformers/mock-import-meta.ts:
import type { ASTTransformer } from 'ts-jest'; const mockImportMetaTransformer: ASTTransformer = (tsJestService) => { const { types: t } = tsJestService; return (context) => ({ visitor: { MemberExpression(path) { // 匹配 import.meta.env.XXX 的结构 if ( t.isMetaProperty(path.node.object) && path.node.object.meta.name === 'import' && path.node.object.property.name === 'meta' && t.isMemberExpression(path.node.property) && path.node.property.object.name === 'env' ) { const envVar = path.node.property.property.name; // 定义模拟的环境变量值 const mockEnv = { API_ENDPOINT: 'https://www.url.com', API_URL: 'https://www.url.com', }; // 替换为对应值,未定义则返回undefined const replacementValue = mockEnv[envVar as keyof typeof mockEnv] ?? undefined; path.replaceWith( replacementValue ? t.stringLiteral(replacementValue) : t.identifier('undefined') ); } }, }, }); }; export default mockImportMetaTransformer;
- 在
jest.config.ts中替换astTransformer配置:
transform: { '^.+\\.tsx?$': [ 'ts-jest', { diagnostics: { ignoreCodes: [1343], }, astTransformers: { before: [ '<rootDir>/src/test/transformers/mock-import-meta.ts' ], }, }, ], },
内容的提问来源于stack exchange,提问作者João Freitas
相关产品推荐
相关产品推荐

