You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

NodeNext模块系统的TS项目中,如何用Jest正确Mock import.meta.url?

NodeNext模块系统下Jest中Mock import.meta.url的TypeScript错误处理

问题背景

在使用NodeNext模块系统的TypeScript项目中,尝试在Jest配置里Mock import.meta.url以设置全局__filename和__dirname,但尽管tsconfig.json已配置"module": "NodeNext",仍触发TypeScript错误:

jest.setup.ts:7:12 - error TS1343: The 'import.meta' meta-property is only allowed when the '--module' option is 'es2020', 'es2022', 'esnext', 'system', 'node16', or 'nodenext'.


相关代码与配置

业务代码(src/index.ts)

import { promises as fs } from 'fs'
import { dirname, join } from 'path'
import { fileURLToPath } from 'url'

const __filename = fileURLToPath(import.meta.url)
const __dirname = dirname(__filename)

/**
 * Returns documentation specific to the provided filename
 * @param {string} filename - The name of the markdown file
 * @returns A promise that resolves to the documentation string
 */
async function getDocumentation(filename: string): Promise<string> {
  const filePath = join(__dirname, filename)
  try {
    const data = await fs.readFile(filePath, 'utf-8')
    return data
  } catch (error) {
    console.error('Error reading documentation file:', error)
    throw new Error('Failed to read documentation file')
  }
}

export { getDocumentation }

tsconfig.json配置

{
  "compilerOptions": {
    "lib": ["dom", "ESNext"],
    "module": "NodeNext",
    "target": "esnext",
    "moduleResolution": "NodeNext",
    "moduleDetection": "force",
    "rootDir": "./",
    "baseUrl": "./",
    "outDir": "./dist",
    "strict": true,
    "isolatedModules": true,
    "strictNullChecks": true,
    "downlevelIteration": false,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true,
    "incremental": true,
    "sourceMap": true,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "resolveJsonModule": true,
    "esModuleInterop": true
  },
  "files": ["src/index.ts", "src/types.d.ts"],
  "include": ["src", "knexfile.ts", "src/types.d.ts"],
  "exclude": ["dist", "*/**/__tests"]
}

jest.config.js配置

module.exports = {
  preset: 'ts-jest',
  testEnvironment: 'node',
  setupFilesAfterEnv: ['./jest.setup.ts'],
  globals: {
    'ts-jest': {
      tsconfig: 'tsconfig.json'
    }
  }
}

当前jest.setup.ts

import { URL } from 'url';
import path from 'path';

const metaUrl = new URL('', import.meta.url).toString();

(global as any).__filename = path.resolve(new URL(metaUrl).pathname);
(global as any).__dirname = path.dirname((global as any).__filename);

jest.mock('url', () => ({
  ...jest.requireActual('url'),
  fileURLToPath: jest.fn((url: string) => {
    if (url === 'file://' + (global as any).__filename) {
      return (global as any).__filename;
    }
    return url;
  }),
}));

解决方案

1. 为测试目录单独配置tsconfig

主tsconfig.json排除了__tests目录,导致Jest处理jest.setup.ts时未应用正确的模块配置。创建tsconfig.test.json:

{
  "extends": "./tsconfig.json",
  "compilerOptions": {
    "module": "NodeNext",
    "moduleResolution": "NodeNext"
  },
  "include": ["src", "__tests__", "jest.setup.ts"]
}

修改jest.config.js中的ts-jest配置,指定测试用的tsconfig:

module.exports = {
  preset: 'ts-jest',
  testEnvironment: 'node',
  setupFilesAfterEnv: ['./jest.setup.ts'],
  globals: {
    'ts-jest': {
      tsconfig: 'tsconfig.test.json'
    }
  }
}

2. 简化Mock逻辑,避免在setup中直接使用import.meta.url

直接通过Jest的mockImplementation处理fileURLToPath,无需手动计算路径:

import { fileURLToPath } from 'url';
import path from 'path';

jest.mock('url', () => ({
  ...jest.requireActual('url'),
  fileURLToPath: jest.fn((url: string) => {
    if (url.startsWith('file://')) {
      return path.resolve(url.replace('file://', ''));
    }
    return url;
  }),
}));

// 直接为全局注入__filename和__dirname
Object.defineProperty(global, '__filename', {
  value: path.resolve(__filename),
});
Object.defineProperty(global, '__dirname', {
  value: path.dirname(__filename),
});

3. 升级依赖确保兼容性

旧版本的ts-jest和jest对NodeNext模块支持不完善,升级到最新稳定版:

npm install -D jest@latest ts-jest@latest typescript@latest

内容的提问来源于stack exchange,提问作者Brayden Langley

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 00:22:17