使用Jest进行TypeScript单元测试时遇ReferenceError: exports is not defined
Jest测试报错
ReferenceError: exports is not defined,指向aws-lambda的import语句 问题背景
执行npm run unit运行单元测试时,tests/unit/get.test.ts用例失败,报错信息如下:
ReferenceError: exports is not defined
错误指向代码行:import { APIGatewayProxyEvent, Context } from 'aws-lambda';
此前为解决Jest encountered an unexpected token问题,已将Jest配置为ESM模式,当前jest.config.ts和测试代码如下:
测试代码
import { describe, expect, it } from '@jest/globals'; import { APIGatewayProxyEvent, Context } from 'aws-lambda'; import { lambdaHandler } from '../../app/app'; describe('Unit test for test', () => { it('test', async () => { // 测试逻辑 const res = lambdaHandler(event, context); expect(res).toEqual('test'); }); });
Jest配置文件
// jest.config.ts export default { preset: 'ts-jest/presets/default-esm', transform: { '^.+\\.ts?$': 'ts-jest', }, clearMocks: true, collectCoverage: true, coverageDirectory: 'coverage', coverageProvider: 'v8', testMatch: ['**/tests/unit/*.test.ts'], testPathIgnorePatterns: ['cf/.aws-sam/build'], moduleNameMapper: { '^/opt/nodejs/dist/db(.*)$': '<rootDir>/../../nodeLayer/db/dist/db$1', }, };
问题原因
核心是ESM与CommonJS模块格式的兼容性冲突:
- 你通过
preset: 'ts-jest/presets/default-esm'让Jest以ESM模式运行,但aws-lambda官方包是基于CommonJS格式开发的(使用module.exports导出) - Jest在ESM模式下加载CommonJS模块时,内部模块处理逻辑会出现混淆,导致
exports变量未定义的错误
解决方案
1. 完善Jest的ESM兼容配置
修改jest.config.ts,显式开启ts-jest的ESM支持,并指定扩展名处理规则:
export default { preset: 'ts-jest/presets/default-esm', transform: { '^.+\\.ts?$': ['ts-jest', { useESM: true // 强制ts-jest以ESM模式处理TypeScript文件 }], }, // 指定将.ts文件当作ESM处理 extensionsToTreatAsEsm: ['.ts'], moduleFileExtensions: ['ts', 'js'], clearMocks: true, collectCoverage: true, coverageDirectory: 'coverage', coverageProvider: 'v8', testMatch: ['**/tests/unit/*.test.ts'], testPathIgnorePatterns: ['cf/.aws-sam/build'], moduleNameMapper: { '^/opt/nodejs/dist/db(.*)$': '<rootDir>/../../nodeLayer/db/dist/db$1', }, };
2. 对齐项目的模块格式配置
检查项目根目录的package.json:
- 如果你的项目是ESM优先:确保存在
"type": "module"字段 - 如果项目以CommonJS为主:可以移除ESM预设,改用
transformIgnorePatterns排除aws-lambda等第三方包的转换(避免Jest尝试转换CommonJS模块):export default { preset: 'ts-jest', // 用默认的CommonJS预设 transform: { '^.+\\.ts?$': 'ts-jest', }, // 排除aws-lambda等CommonJS包的转换 transformIgnorePatterns: ['/node_modules/(?!aws-lambda)/'], // 其他原有配置... };
3. 升级依赖包版本
部分旧版本的ts-jest和jest在ESM与CommonJS混合场景下存在bug,升级到最新稳定版可解决大部分兼容性问题:
npm install -D jest@latest ts-jest@latest @types/jest@latest
4. 临时兼容方案(不推荐长期使用)
如果上述方法都无效,可以临时改用require导入aws-lambda模块:
import { describe, expect, it } from '@jest/globals'; // 用require替代import加载CommonJS模块 const { APIGatewayProxyEvent, Context } = require('aws-lambda'); import { lambdaHandler } from '../../app/app';
额外检查点
- 确认
tsconfig.json中的module字段设置为ESNext或ES6+,与Jest的ESM配置保持一致 - 检查业务代码
app/app.ts的导出方式,确保使用export或export default的ESM语法,避免混合CommonJS导出
内容的提问来源于stack exchange,提问作者kyoshida
相关产品推荐
相关产品推荐

