NestJS项目Jest测试时无法找到模块,正常运行无异常
问题:Jest测试无法识别TS路径别名
场景说明
NestJS项目中编写PlaceController的单元测试,测试文件place.controller.spec.ts与控制器、服务文件同级。正常启动应用后接口可正常调用,但运行npm run test时出现模块找不到错误。
测试文件代码(place.controller.spec.ts)
import { Test, TestingModule } from '@nestjs/testing'; import { PlaceController } from './place.controller'; import { PlaceService } from './place.service'; import { expect } from 'chai'; describe('PlaceController', () => { let appController: PlaceController; beforeEach(async () => { const app: TestingModule = await Test.createTestingModule({ controllers: [PlaceController], providers: [PlaceService], }).compile(); appController = app.get<PlaceController>(PlaceController); }); it('should be defined', () => { expect(appController).toBeDefined(); }); });
Jest配置(jest.config.ts)
/** @type {import('ts-jest/dist/types').InitialOptionsTsJest} */ module.exports = { preset: 'ts-jest', testEnvironment: 'node', testMatch: ['**/**/*.spec.ts'], verbose: true, forceExit: true, clearMocks: true, resetMocks: true, restoreMocks: true, bail: false, };
根目录tsconfig.json
{ "compileOnSave": false, "compilerOptions": { "baseUrl": "./src", "outDir": "./dist", "incremental": true, "sourceMap": true, "declaration": false, "removeComments": true, "downlevelIteration": true, "emitDecoratorMetadata": true, "experimentalDecorators": true, "module": "commonjs", "moduleResolution": "node", "importHelpers": true, "skipLibCheck": true, "target": "es2017", "typeRoots": [ "node_modules/@types" ], "lib": [ "es2018", "dom" ], "paths": { "@app/*": [ "./client/app/*" ], "@assets/*": [ "./client/assets/*" ], "@env/*": [ "./client/environments/*" ], "@common/*": [ "./common/*" ], "@server/*": [ "./server/*" ] } }, }
控制器目录上两级的tsconfig.json
{ "extends": "../../tsconfig.json", "exclude": ["node_modules", "test", "dist"] }
package.json测试脚本
"test": "NODE_ENV=test jest"
报错信息
Cannot find module '@server/app/api/place/place.dto' from 'src/server/app/api/place/place.controller.ts' Require stack: src/server/app/api/place/place.controller.ts src/server/app/api/place/place.controller.spec.ts > 1 | import { CreatePlaceDto } from '@server/app/api/place/place.dto'; | ^ 2 | import { PlaceService } from '@server/app/api/place/place.service'; 3 | import { CrudRequest } from '@server/app/core/crud/crud'; 4 | import {
问题原因
- Jest不默认识别TS路径别名:
tsconfig.json中的paths配置是给TypeScript编译器用的,Jest运行时无法直接解析这些别名,需要单独配置路径映射。 - 子目录TS配置排除了测试文件:控制器所在目录的上级
tsconfig.json中exclude包含了test目录,导致测试文件编译时无法继承根目录的路径别名配置,进一步加剧了模块解析失败的问题。
解决步骤
步骤1:在Jest配置中添加路径映射
修改jest.config.ts,添加moduleNameMapper字段,将TS的paths配置映射为Jest能识别的格式,并指定Jest使用根目录的tsconfig:
/** @type {import('ts-jest/dist/types').InitialOptionsTsJest} */ module.exports = { preset: 'ts-jest', testEnvironment: 'node', testMatch: ['**/**/*.spec.ts'], verbose: true, forceExit: true, clearMocks: true, resetMocks: true, restoreMocks: true, bail: false, // 添加路径映射 moduleNameMapper: { '^@app/(.*)$': '<rootDir>/src/client/app/$1', '^@assets/(.*)$': '<rootDir>/src/client/assets/$1', '^@env/(.*)$': '<rootDir>/src/client/environments/$1', '^@common/(.*)$': '<rootDir>/src/common/$1', '^@server/(.*)$': '<rootDir>/src/server/$1', }, // 指定Jest使用根目录的tsconfig globals: { 'ts-jest': { tsconfig: './tsconfig.json', }, }, };
步骤2:调整子目录TS配置(可选)
如果子目录的tsconfig.json不需要排除测试文件,可以修改exclude字段,移除test:
{ "extends": "../../tsconfig.json", "exclude": ["node_modules", "dist"] }
或者保持原配置,依赖步骤1中指定的根目录tsconfig即可。
内容的提问来源于stack exchange,提问作者Kaisin Li
相关产品推荐
相关产品推荐

