在Jest中导入ECMAScript包:动态import无法正常工作
问题:E2E测试中动态加载ESM包报错,运行时正常
现象
运行npm run start时功能正常,但端到端测试中加载ECMAScript包时触发错误:
TypeError: A dynamic import callback was not specified.
11 | useFactory: async () => { 12 | try { >13 | const pRetryPkg = await import(P_RETRY_PACKAGE_NAME);错误代码:
ERR_VM_DYNAMIC_IMPORT_CALLBACK_MISSING
相关代码
import { Provider } from '@nestjs/common'; export const P_RETRY_PACKAGE_NAME = 'p-retry'; export interface PRetryEsmPackage { <T>(input: (attemptCount: number) => PromiseLike<T> | T, options?: Record<string, unknown>): Promise<T>; } export const PRetryPackageProvider: Provider = { provide: P_RETRY_PACKAGE_NAME, useFactory: async () => { try { const pRetryPkg = await import(P_RETRY_PACKAGE_NAME); return pRetryPkg.default as PRetryEsmPackage; } catch (error) { console.error(`Failed to load ${P_RETRY_PACKAGE_NAME}: ${error.message}`); throw error; // Re-throwing to ensure the provider fails if it's essential } }, };
已完成的配置
- 已设置环境变量
NODE_OPTIONS=--experimental-vm-modules - tsconfig核心配置:
{ "compilerOptions": { ... "target": "ES2017", "module": "NodeNext", "emitDecoratorMetadata": true, "allowSyntheticDefaultImports": true, "incremental": true, "skipLibCheck": true, "moduleResolution": "NodeNext" } }
调试建议
- 确认Jest的ESM模式完全启用:
检查jest.config.js(或jest.config.ts)中是否设置type: 'module',同时确保测试文件使用.mts/.mjs扩展名,或在项目根目录的package.json中添加"type": "module"。混用CommonJS与ESM模块可能导致动态import回调缺失。 - 替换动态import的变量为字面量:
临时将await import(P_RETRY_PACKAGE_NAME)改为await import('p-retry')测试。Jest在VM模块模式下处理动态变量的ESM导入时,可能存在兼容性问题。 - 验证环境变量是否生效:
在测试脚本中添加console.log(process.env.NODE_OPTIONS),确认--experimental-vm-modules已被正确传入。跨平台环境下可使用cross-env确保变量传递正常。 - 禁用Jest缓存:
运行测试时添加--no-cache参数,避免旧编译缓存引发的模块加载异常。 - 检查p-retry包的导出格式:
查看p-retry包的package.json,确认type字段是否为module,或是否同时提供ESM与CommonJS版本。若包为纯ESM,需确保Jest正确识别其模块类型。 - 临时替换为静态导入测试:
将动态import改为静态导入import pRetry from 'p-retry',若测试正常运行,说明问题出在动态import的VM模块处理上。可考虑在测试环境中提供Mock Provider替代动态加载逻辑。
内容的提问来源于stack exchange,提问作者klettg
相关产品推荐
相关产品推荐

