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

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 {

问题原因

  1. Jest不默认识别TS路径别名:tsconfig.json中的paths配置是给TypeScript编译器用的,Jest运行时无法直接解析这些别名,需要单独配置路径映射。
  2. 子目录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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 06:10:47