Angular 20升级至21后单元测试报模块未找到错误
Angular 20升级至21后Jest单元测试模块找不到问题
问题概述
将Angular从20版本升级到21版本后,所有单元测试全部失败,报错提示找不到@angular/core/testing、@angular/common/http/testing或@angular/common/http模块。VS Code中输入import TestBed能正常自动补全,说明模块文件存在,但执行npm run test(实际映射为Jest命令)时测试失败,推测是Jest或TypeScript的路径识别问题,调整配置文件后仍未解决。
错误信息
src/app/service/user-group-service.spec.ts:1:25 - error TS2307: Cannot find module '@angular/core/testing' or its corresponding type declarations. 1 import { TestBed } from '@angular/core/testing'; ~~~~~~~~~~~~~~~~~~~~~~~ src/app/service/user-group-service.spec.ts:3:65 - error TS2307: Cannot find module '@angular/common/http/testing' or its corresponding type declarations. 3 import { HttpTestingController, provideHttpClientTesting } from '@angular/common/http/testing'; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ src/app/service/user-group-service.spec.ts:4:35 - error TS2307: Cannot find module '@angular/common/http' or its corresponding type declarations. 4 import { provideHttpClient } from '@angular/common/http'; ~~~~~~~~~~~~~~~~~~~~~~
环境版本信息
$ ng version Angular CLI : 21.2.12 Angular : 21.2.14 Node.js : 22.22.2 Package Manager : npm 11.12.0 Operating System : darwin arm64 ┌───────────────────────────────────┬───────────────────┬───────────────────┐ │ Package │ Installed Version │ Requested Version │ ├───────────────────────────────────┼───────────────────┼───────────────────┤ │ @angular-devkit/build-angular │ 21.2.12 │ ~21.2.12 │ │ @angular/animations │ 21.2.14 │ ~21.2.14 │ │ @angular/cdk │ 20.2.14 │ ^20.2.14 │ │ @angular/cli │ 21.2.12 │ ~21.2.12 │ │ @angular/common │ 21.2.14 │ ~21.2.14 │ │ @angular/compiler │ 21.2.14 │ ~21.2.14 │ │ @angular/compiler-cli │ 21.2.14 │ ~21.2.14 │ │ @angular/core │ 21.2.14 │ ~21.2.14 │ │ @angular/forms │ 21.2.14 │ ~21.2.14 │ │ @angular/language-service │ 21.2.14 │ ~21.2.14 │ │ @angular/platform-browser │ 21.2.14 │ ~21.2.14 │ │ @angular/platform-browser-dynamic │ 21.2.14 │ ~21.2.14 │ │ @angular/router │ 21.2.14 │ ~21.2.14 │ │ rxjs │ 7.8.2 │ ~7.8.2 │ │ typescript │ 5.9.3 │ ^5.9.3 │ │ zone.js │ 0.15.1 │ ~0.15.1 │ └───────────────────────────────────┴───────────────────┴───────────────────┘
配置文件内容
tsconfig.json
{ "compileOnSave": false, "isolatedModules": true, "compilerOptions": { "baseUrl": "./", "outDir": "./dist/out-tsc", "esModuleInterop": true, "sourceMap": true, "declaration": false, "module": "es2015", "moduleResolution": "bundler", "experimentalDecorators": true, "importHelpers": false, "target": "es2022", "typeRoots": [ "node_modules/@types" ], "useDefineForClassFields": false } }
jest.config.ts
import type { Config } from 'jest'; const config: Config = { verbose: true, preset: 'jest-preset-angular', injectGlobals: true, testEnvironment: 'jest-environment-jsdom', transform: { '^.+\\.(ts|mjs|js|html)$': [ 'jest-preset-angular', { tsconfig: '<rootDir>/tsconfig.spec.json', stringifyContentPathRegex: '\\.(html|svg)$', useESM: true, }, ], }, reporters: ['jest-simple-dot-reporter'], setupFilesAfterEnv: ['<rootDir>/setup-jest.ts'], modulePathIgnorePatterns: [ // These ignores are needed when run inside the container "<rootDir>/.SAVED", "<rootDir>/.container_node_modules_amd64" ], moduleNameMapper: { '^src/(.*)$': '<rootDir>/src/$1', '^app/(.*)$': '<rootDir>/src/app/$1', '^assets/(.*)$': '<rootDir>/src/assets/$1', '^environments/(.*)$': '<rootDir>/src/environments/$1', }, collectCoverage: true, collectCoverageFrom: [ // '**/*.{ts,js,jsx}', 'src/**/*.{ts,js,jsx}', '!src/environments/**' ], coverageProvider: 'v8', coverageReporters: [ 'html', 'text-summary', ], coveragePathIgnorePatterns: [ 'src/app/model', 'src/app/mailing-lists/model', 'src/main.ts', 'src/polyfills.ts', 'src/zone-flags.ts', 'src/app/app.module.ts', ] }; export default config;
tsconfig.spec.json
{ "compileOnSave": false, "extends": "./tsconfig.json", "include": ["src/**/*.spec.ts", "src/**/*.d.ts"], "compilerOptions": { "baseUrl": "./", "outDir": "./dist/out-tsc", "esModuleInterop": true, "sourceMap": true, "declaration": false, "module": "es2015", "moduleResolution": "node", "experimentalDecorators": true, "importHelpers": true, "target": "ESNext", "types": ["jest", "node"], "typeRoots": [ "node_modules/@types" ], "lib": [ "es2018", "dom" ], "useDefineForClassFields": false } }
排查与解决建议
- 升级jest-preset-angular版本:Angular 21需要兼容的jest-preset-angular版本,执行
npm install jest-preset-angular@latest --save-dev升级到最新稳定版,确保适配Angular 21的ESM格式。 - 统一moduleResolution配置:主tsconfig使用
bundler,而spec配置使用node会导致解析不一致,将tsconfig.spec.json中的moduleResolution改为bundler,保持与主配置一致。 - 清理并重新安装依赖:删除
node_modules、package-lock.json文件,执行npm install重新安装所有依赖,避免版本不兼容或缓存问题。 - 调整TypeScript模块设置:将
tsconfig.spec.json中的module改为ESNext,匹配Angular 21的ESM要求,同时确保jest.config.ts中的useESM: true已启用。 - 检查路径映射是否冲突:确认
jest.config.ts中的moduleNameMapper没有覆盖Angular官方模块路径,避免Jest错误解析模块位置。
内容的提问来源于stack exchange,提问作者commadelimited
相关产品推荐
相关产品推荐

