在 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'
模块。
错误指示符(>
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.json
和jest.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",
<rootDir>
如果自动定义,则指向package.json
目录
"@modules/(.*)"
是一个正则表达式,用于“任何以 '@module/' 开头的字符串,后跟任何字符串
"<rootDir>/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 在这种情况下,前缀应该设置为现在我们使用一种解决方法:我们在 mono-repo 的多个 tsconfig.json 文件中定义了路径。我们将所有路径移至 root-tsconfig,现在测试再次运行。 但我们并不真正理解为什么会这样。
还有一个缺点是现在很容易意外引用您不应该在 lib 中使用的路径(因为 IDE 现在总是使用所有路径进行代码辅助)
【讨论】:
以上是关于在 CI 中使用 typescript 路径开玩笑“找不到模块”的主要内容,如果未能解决你的问题,请参考以下文章
用 TypeScript 开玩笑:TypeError: environment.teardown 不是函数
如何允许 scss 开玩笑地对 typescript nextjs 进行单元测试?
带有 Typescript 错误的玩笑:超时 - 在 jest.setTimeout.Timeout 指定的 5000 毫秒超时内未调用异步回调