Nx 仓库导入后 Jest 测试集成指南:`@nx/jest/plugin`、`jest.preset.js` 与常见问题修复
发布时间:2026/9/9 23:59:09 作者:尧图编辑部 阅读量:1,286

Nx 仓库导入后 Jest 测试集成指南nx/jest/plugin、jest.preset.js与常见问题修复【免费下载链接】nxThe Monorepo Platform that amplifies both developers and AI agents. Nx optimizes your builds, scales your CI, and fixes failed PRs automatically. Ship in half the time.项目地址: https://gitcode.com/GitHub_Trending/nx/nx在使用nx import将外部仓库合并进 Nx workspace 后Jest 测试往往不会开箱即用测试 target 缺失、类型定义无法识别、transform 未配置、甚至package.json里的测试脚本被改坏。本文以 .opencode/skills/nx-import/references/JEST.md 为骨架结合当前 Nx 仓库中 packages/jest 的插件源码、生成器实现与真实配置文件系统讲解导入后 Jest 集成的完整链路——从插件推断机制、preset 与 tsconfig 配置到依赖安装、Jest/Vitest 共存、CI 原子化与最终修复顺序。读完你可以独立完成任意仓库导入后的 Jest 测试修复与 CI 配置。适用前提本指南面向使用nx import参见 .opencode/skills/nx-import/SKILL.md合并仓库的场景。关于基础的Jest Preset Missing修复创建jest.preset.js并安装依赖SKILL.md 中有简化说明本文覆盖更深层的集成问题。nx/jest/plugin的工作原理插件如何推断 test targetnx/jest/plugin是一个 Nx 推断型插件inference plugin。它扫描工作区中符合**/jest.config.{cjs,mjs,js,cts,mts,ts}模式的文件为每个配置存在的项目创建一个testtarget。这个 glob 定义在 packages/jest/src/plugins/plugin.tsconst jestConfigGlob **/jest.config.{cjs,mjs,js,cts,mts,ts};插件在createNodes中完成两件事并行加载所有 Jest 配置通过loadConfigFile并优先查找tsconfig.spec.json、tsconfig.test.json、tsconfig.jest.json、tsconfig.json为每个项目构建 targets默认 target 名为test执行命令为jest且会从 Jest 配置里解析出preset、setupFiles、moduleNameMapper等外部引用自动推导任务inputs与outputs缓存与增量测试的基础。注意插件的项目判定逻辑checkIfConfigFileShouldBeProject如果某个jest.config.*所在目录既没有package.json也没有project.json插件不会为它创建项目如果配置内容包含getJestProjectsAsync()也会被跳过——因为该函数依赖项目图会形成循环依赖。插件配置选项在nx.json中注册插件时可以传入选项{ plugin: nx/jest/plugin, options: { targetName: test } }从源码JestPluginOptionspackages/jest/src/plugins/plugin.ts可以看到完整选项选项默认值作用targetNametest推断出的测试 target 名称ciTargetName无开启 CI 原子化每文件一个 target时使用的聚合 target 名如test-ciciGroupName由ciTargetName推导CI 原子化任务在 Nx Cloud 上的分组名disableJestRuntimefalse是否使用 Nx 自己的配置加载器与测试匹配器替代jest-config/jest-runtime禁用后更快但可能在边界情况下不如 Jest 自身正确useJestResolver与disableJestRuntime相反是否用 Jest 的 resolver 解析 preset、transform、setup 文件等引用作为任务 inputs能跟随 symlink、支持moduleDirectories/modulePathsnormalizeOptions中targetName ?? testpackages/jest/src/plugins/plugin.ts保证未配置时默认为test。npx nx add nx/jest到底做了什么npx nx add nx/jest会执行 init 生成器packages/jest/src/generators/init/init.ts主要做两件事在nx.json中注册nx/jest/plugin——没有它任何testtarget 都不会被推断出来更新namedInputs.production将测试相关文件从生产文件集排除productionFileSet.push( !{projectRoot}/**/?(*.)(spec|test).[jt]s?(x)?(.snap), !{projectRoot}/tsconfig.spec.json, !{projectRoot}/jest.config.[jt]s, !{projectRoot}/src/test-setup.[jt]s, !{projectRoot}/test-setup.[jt]s );此外当工作区走显式 executornx/jest:jest路径时init 生成器还会通过upsertTargetDefault写入 target 默认值cache: true、inputsdefault^production{workspaceRoot}/jest.preset.*、options.passWithNoTests: true以及ci配置ci: true, codeCoverage: true。两个关键陷阱原文档特别强调nx add nx/jest不会创建jest.preset.js。该文件只在运行生成器如nx/jest:configuration时才会生成。对于nx import的场景你必须手动创建见下一节。反过来如果你手动创建了jest.preset.js却跳过了npx nx add nx/jest插件未注册nx run PROJECT:test会报Cannot find target test。两者缺一不可。Jest Preset共享配置的基石根目录jest.preset.jspreset 提供了共享的 Jest 配置测试匹配模式、ts-jest transform、resolver、jsdom 环境等。最小写法const nxPreset require(nx/jest/preset).default; module.exports { ...nxPreset };当前 Nx 仓库根目录的真实 jest.preset.js 展示了在nxPreset基础上覆盖更多选项的写法设置testTimeout、用swc/jest替换默认的 ts-jest transform、覆盖testEnvironment为node、配置moduleNameMapper将 ESM-only 的clack/prompts、ora、prettier等替换为 scripts/jest-mocks 下的 mock 实现并通过setupFiles引入 scripts/unit-test-setup.js。这提示你preset 是 workspace 级约定的最佳落点。nxPreset的默认值nxPreset定义在 packages/jest/preset/jest-preset.ts核心默认值如下配置项默认值说明testMatch**/?(*.)(spec|test).[jt]s?(x)Jest 30 起支持?([mc])变体匹配 spec/test 文件resolvernx/jest/plugins/resolverNx 自定义 resolver处理 monorepo 内跨包解析moduleFileExtensions[ts, js, mjs, html]Jest 30 起增加 mts/cts/cjs支持 TypeScript 与 Angular 模板coverageReporters[html]覆盖率输出格式transformts-jesttsconfig: rootDir/tsconfig.spec.json默认用 ts-jest 转译testEnvironmentjsdom注意Nx preset 默认是 jsdom纯 Node 项目需显式覆盖为nodemodulePathIgnorePatterns[rootDir/dist/, rootDir/out-tsc/]忽略构建产物testEnvironmentOptions.customExportConditions[node, require, default]强制 Jest 加载 CommonJS 代码规避 ESM 兼容问题项目级jest.config.ts每个项目通过相对路径引用根 presetexport default { displayName: my-lib, preset: ../../jest.preset.js, // project-specific overrides };preset路径是相对项目根目录到 workspace 根目录的。子目录导入时保留原始相对路径如../../jest.preset.js只要导入目标目录与源目录深度一致该相对路径即可正确解析。当前仓库 e2e 测试 e2e/jest/src/jest.test.ts 中生成的配置同样使用了preset: ../../jest.preset.js与[ts-jest, { tsconfig: rootDir/tsconfig.spec.json }]的 transform可作为标准样板。测试依赖安装核心依赖始终需要pnpm add -wD jest ts-jest types/jest nx/jest-wD表示安装到 workspace 根目录的 devDependencies。Jest 30 起还会依赖unrs-resolverinit 生成器中已通过acknowledgeBuildScripts处理其 postinstallpackages/jest/src/generators/init/init.ts。按环境区分DOM 测试React、Vue、浏览器类库需要jest-environment-jsdom因为nxPreset默认testEnvironment: jsdomNode 测试API、CLI无需额外依赖。Jest 默认是node环境但 Nx preset 默认是jsdom——因此 Node 项目要在项目级jest.config.ts中显式覆盖testEnvironment: node仓库根 jest.preset.js 就是这么做的。React 测试pnpm add -wD testing-library/react testing-library/jest-domReact Babel非 ts-jest transform部分 React 项目老 Nx workspace、CRA 迁移项目用 Babel 而非 ts-jest 做 JSX 转译pnpm add -wD babel-jest babel/core babel/preset-env babel/preset-react babel/preset-typescript何时需要项目jest.config的transform使用的是babel-jest而不是ts-jest。判断方法就是检查jest.config.*中的 transform 段。Vue 测试pnpm add -wD vue/test-utils注意Vue 项目通常使用 Vitest 而非 Jest——详见 .opencode/skills/nx-import/references/VITE.md。tsconfig.spec.json测试文件的类型配置每个 Jest 项目都需要一个包含测试文件的tsconfig.spec.json。标准模板{ extends: ./tsconfig.json, compilerOptions: { outDir: ../../dist/out-tsc, module: commonjs, types: [jest, node] }, include: [ jest.config.ts, src/**/*.test.ts, src/**/*.spec.ts, src/**/*.d.ts ] }当前仓库 e2e 项目的真实配置 e2e/jest/tsconfig.spec.json 还额外展示了isolatedModules: true、rootDir: .以及exclude: [out-tsc]的写法include 数组覆盖了**/*.test.ts、**/*.spec.ts、JS/JSX 变体与jest.config.ts可直接作为参考。导入后常见问题缺少types: [jest, node]→describe/it/expect全部无法识别报Cannot find type definition file for jest缺少module: commonjs→ Jest 默认不支持 ESMts-jest 转译为 CJS报Cannot use import statement outside a moduleinclude数组缺少测试文件模式 → TypeScript 根本不会检查测试文件类型错误被静默吞掉。注意types数组是显式列举而非自动发现因此types/jest必须安装且必须写入types而 ts-jest 的 transform 会读取rootDir/tsconfig.spec.json所以该文件路径与内容必须与 preset/项目配置对齐。Jest 与 Vitest 共存一个 workspace 可以同时存在两套测试体系JestNext.js 应用、老 React 库、Node 库Vitest基于 Vite 的 React/Vue 应用与库。nx/jest/plugin与nx/vite/plugin后者推断 Vitest target互不冲突——它们检测不同的配置文件jest.config.*vsvite.config.*见 packages/jest/src/plugins/plugin.ts 中的配置 glob 与 Vite 插件的vite.config.*匹配。唯一注意点两者默认 target 名都是test。如果某个项目异常地同时拥有两套配置文件需要重命名其中一个{ plugin: nx/jest/plugin, options: { targetName: jest-test } }另外init 生成器在注册插件时默认会同时接受test、jest:test、jest-test三个 target 名targetName: [test, jest:test, jest-test]为的就是与既有脚本或显式 target 平滑共存。testing-library/jest-domJest 与 Vitest 的导入差异从 Jest 迁移到 Vitest或两者共存的项目需要不同的导入路径。在test-setup.ts中Jestimport testing-library/jest-dom;Vitestimport testing-library/jest-dom/vitest;如果源仓库用的是 Jest 而目标 workspace 对该类项目使用 Vitest记得更新导入路径并把testing-library/jest-dom加入 tsconfig 的types数组。非 Nx 源仓库package.json测试脚本重写问题导入非 Nx 源仓库时Nx 在 init 期间会重写package.json脚本测试脚本尤其容易损坏test: jest→test: nx test没有配置 executor 时形成循环调用test: vitest run→test: nx test run损坏——run变成了参数。修复删除所有被重写的测试脚本。nx/jest/plugin与nx/vite/plugin会从配置文件推断 test targetpackage.json里不需要也不应该有重复的测试脚本。同理如果源项目自带build/dev/start/lint脚本Nx 插件会自动给推断 target 加前缀如next:build、vite:build、eslint:lint以避免冲突——要么接受前缀名nx run app:next:build要么在nx.json中重命名插件 target 名去掉前缀。CI 原子化Atomizationnx/jest/plugin支持按文件拆分测试任务用于 CI 并行{ plugin: nx/jest/plugin, options: { targetName: test, ciTargetName: test-ci } }配置后插件为每个测试文件生成形如test-ci--src/lib/foo.spec.ts的独立 target并创建一个名为test-ci的聚合 targetexecutor 为nx:noop通过dependsOn转发参数和选项到各原子任务。每个原子任务执行jest relativePath继承cache、inputs、outputs。这些任务通过targetGroups分组ciGroupName可直接由 Nx Cloud 分发执行。从源码看packages/jest/src/plugins/plugin.ts原子化还有几个细节通过 Jest 的SearchSource/getTestPaths或 Nx 自己的globWithWorkspaceContext枚举测试文件并按路径排序保证 target 名稳定尊重testPathIgnorePatterns被忽略的文件不会生成原子任务如果测试文件超出项目根目录会直接报错防止错误配置静默放行聚合 target 的 metadata 中包含nonAtomizedTarget: test标记它对应的完整测试 target。导入阶段用不到原子化但它是导入后 CI 改造的直接收益点。常见导入后问题清单#错误信息根因修复1Cannot find target testnx/jest/plugin未注册到nx.jsonnpx nx add nx/jest或手动添加插件条目2Cannot find module jest-presetworkspace 根目录缺少jest.preset.js手动创建见上文 preset 一节3Cannot find type definition file for jest缺少types/jest或tsconfig.spec.json没有types: [jest, node]安装依赖并修正 tsconfig4Cannot use import statement outside a modulets-jest 未安装或未配置为 transform安装 ts-jest检查jest.config.*的 transform 段5快照路径不匹配导入后__snapshots__目录路径已固化带--updateSnapshot跑一次测试重新生成前两类问题与Jest Preset Missing基础修复的完整步骤同样记录在 .opencode/skills/nx-import/SKILL.md本文不再重复。推荐修复顺序子目录导入目标为 Nx 源npx nx add nx/jest—— 在nx.json注册插件不会创建jest.preset.js手动创建jest.preset.js内容见上文安装核心依赖pnpm add -wD jest jest-environment-jsdom ts-jest types/jest按框架安装测试依赖React 装testing-library/react testing-library/jest-domVue 装vue/test-utils核对tsconfig.spec.json包含types: [jest, node]运行nx run-many -t test验证。整仓导入非 Nx 源删除package.json中被重写的测试脚本npx nx add nx/jest—— 注册插件不创建 preset手动创建jest.preset.js安装依赖同上核对/修复jest.config.*—— 确保preset路径指向根目录jest.preset.js核对/修复tsconfig.spec.json—— 补上types、module、include运行nx run-many -t test验证。验证与进一步阅读修复完成后可以用 packages/jest/PLUGIN.md 中的命令做日常验证与单文件调试推断模式nx/jest/pluginnx test project -- --testPathPatternpath/to/file.spec.ts按名称过滤用nx test project -- -t pattern显式 executor 模式nx/jest:jestnx run project:test --testFilepath/to/file.spec.ts按名称过滤用nx run project:test --testNamePatternpattern。插件本身的行为由 packages/jest/src/plugins/plugin.spec.ts 等测试保障如果想深入理解 preset 默认值直接阅读 packages/jest/preset/jest-preset.ts生成器的完整流程含nx/jest:configuration如何同时创建 preset 与项目配置见 packages/jest/src/generators/configuration/configuration.ts。【免费下载链接】nxThe Monorepo Platform that amplifies both developers and AI agents. Nx optimizes your builds, scales your CI, and fixes failed PRs automatically. Ship in half the time.项目地址: https://gitcode.com/GitHub_Trending/nx/nx创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考