在 CI 中使用 typescript 路径开玩笑“找不到模块”

Posted

技术标签:

【中文标题】在 CI 中使用 typescript 路径开玩笑“找不到模块”【英文标题】:Jest "Cannot find module" with typescript paths in CI 【发布时间】:2020-03-25 17:55:15 【问题描述】:

在 Gitlab-CI 环境中,我们的 Jest 测试 2 失败并显示 Cannot find module。 奇怪的是它可以在我的本地 Win10 机器上运行——即使我在类似的 docker-container (node 12.12.0) 中运行测试。

这是控制台输出:

FAIL apps/server/src/domain/dashboard/permission-group.service.spec.ts
Test suite failed to run
  Cannot find module '@cm/utils-server' from 'license.service.ts'
     9 |   isLicenseFileContent,
    10 |   LicenseStatus,
  > 11 |   parseLicenseInfo
       |                   ^
    12 |  from '@cm/license-shared';
    13 | import  ExitCode  from '../../util/exit-codes';
    14 | import  readFile  from '@cm/utils-server';
    at Resolver.resolveModule (../../node_modules/jest-resolve/build/index.js:259:17)
    at Object.<anonymous> (src/domain/license/license.service.ts:11:24)

我不确定如何正确解释这个输出:

    permission-group.service.spec.ts:这是失败的测试 Cannot find module '@cm/utils-server' from 'license.service.ts': 好的,测试或它的一些依赖项,使用license.service.ts 并且在license.service.ts 文件中找不到'@cm/utils-server' 模块。 错误指示符(&gt;parseLicenseInfo)是什么意思? 这是用于导入 @cm/license-shared - 不是用于 @cm/utils-server,如 2 中的错误消息所示 @cm/utils-server 也被导入,但在第 14 行下面有 2 行:所以这可能只是一个开玩笑的错误吗?

【问题讨论】:

遇到同样的问题...如果您找到解决方案,我很乐意听到。 @Donovan 目前只是一种解决方法:我们在 mono-repo 的多个 tsconfig.json 文件中定义了 paths。我们将所有路径移至 root-tsconfig,现在测试再次运行。但我们并不真正理解为什么会这样。这有一个缺点,现在很容易意外引用您不应该在 lib 中使用的路径(因为 IDE 现在总是使用所有路径来进行代码辅助) 【参考方案1】:

我刚遇到这个问题并搜索了一些解决方案。找到了this 站点,该站点提供了有关可以做什么的线索:配置 Jest 的 moduleNameMapper 属性。

所以,阅读documentation 我找到了这个解决方案:

    打开tsconfig.jsonjest.config.js 文件(或等效文件)

    tsconfig.json 中,找到您的绝对路径定义。我的配置如下:

"paths": 
    "@modules/*": ["modules/*"],
    "@config/*": ["config/*"],
    "@shared/*": ["shared/*"]

    jest.config.json 中,找到moduleNameMapper 属性并取消注释,然后开始将您的TS 绝对路径转换为Jest 映射器语法。听起来很复杂,但其实不然:
moduleNameMapper: 
    "@modules/(.*)": "<rootDir>/src/modules/$1",
    "@config/(.*)": "<rootDir>/src/config/$1",
    "@shared/(.*)": "<rootDir>/src/shared/$1",

&lt;rootDir&gt; 如果自动定义,则指向package.json 目录 "@modules/(.*)" 是一个正则表达式,用于“任何以 '@module/' 开头的字符串,后跟任何字符串 "&lt;rootDir&gt;/src/modules/$1" 是对应的目录。 $1 是指向括号 ((.*)) 之间的正则表达式的指针。其他表达式会被$2$3等指向

完成此操作后,我能够毫无问题地执行我的测试。

执行上述步骤之前的控制台输出:

$ jest
 FAIL  src/modules/appointments/services/CreateAppointmentService.spec.ts
  ● Test suite failed to run

    Cannot find module '...'

之后的控制台输出:

$ jest
 PASS  src/modules/appointments/services/CreateAppointmentService.spec.ts

希望这对某人有所帮助, 谢谢!

【讨论】:

可以通过ts-jest/utils中的pathsToModuleNameMapper()方法进行简化。 kulshekhar.github.io/ts-jest/docs/getting-started/paths-mapping 在这种情况下,前缀应该设置为 /src【参考方案2】:

现在我们使用一种解决方法:我们在 mono-repo 的多个 tsconfig.json 文件中定义了路径。我们将所有路径移至 root-tsconfig,现在测试再次运行。 但我们并不真正理解为什么会这样。

还有一个缺点是现在很容易意外引用您不应该在 lib 中使用的路径(因为 IDE 现在总是使用所有路径进行代码辅助)

【讨论】:

以上是关于在 CI 中使用 typescript 路径开玩笑“找不到模块”的主要内容,如果未能解决你的问题,请参考以下文章

用 Quasar 和 Typescript 开玩笑

用 TypeScript 开玩笑:TypeError: environment.teardown 不是函数

如何允许 scss 开玩笑地对 typescript nextjs 进行单元测试?

带有 Typescript 错误的玩笑:超时 - 在 jest.setTimeout.Timeout 指定的 5000 毫秒超时内未调用异步回调

赛普拉斯在开玩笑断言中导致类型错误

用于 Typescript 的 Sonarqube 上未显示代码覆盖率