JEST:尽管使用了未知组件,但单元测试成功

JEST: unit tests are successful although an unknown component is used

为什么即使使用了不存在但在 bitbucket 管道中的组件,单元测试也不会在本地失败?

为了演示这个问题,我创建了一个新的 nx 工作区 (Repository)。

本地运行 'npx jest'时,出现console.error组件未知,但测试未失败。另一方面,相同的命令在管道中导致相反的情况 (Pipeline)。这对我们来说是个大问题,因为让单元测试只在管道中失败,我们浪费了很多时间来重新启动它们并 运行。

我认为您正面临这个问题:https://github.com/angular/angular/issues/36430 and this user has the exact same issue as you: https://github.com/angular/angular/issues/36430#issuecomment-611374846

现在为什么它在 Bitbucket 管道上失败而不是在本地很奇怪。

你可以尝试做的是在 test.ts 添加类似的行到 test.ts:

console.warn = function (message?: any, ...optionalParams: any[]): void {
  console.log({ message, optionalParams });
  fail('Test emitted a console warning!', message);
};
console.error = function (message?: any, ...optionalParams: any[]): void {
  console.log({ message, optionalParams });
  fail('Test emitted a console error!', message);
};

我们正在覆盖 console.error 和 console.warn 的定义以使测试失败。

那么单元测试应该失败并出现 is not a known element 错误。

请注意,现在如果您的单元测试有 console.error 或 console.warn,单元测试将失败。

正如 AliF50 正确识别的那样,您的问题是由于 angular 根据某些设置组件以不同方式处理缺失的元素类型。 Monkey patching console.error 绝对是避免在本地出现此错误的可行解决方案。 但是您的构建在 bitbucket 管道中表现不同的原因是另外一回事。 如果您查看管道步骤 npm ci 的日志输出,您可以看到最后一条日志消息是:

npm WARN lifecycle pipeline-jest-test@0.0.0~postinstall: cannot run in wd pipeline-jest-test@0.0.0 node ./decorate-angular-cli.js && ngcc --properties es2015 browser module main (wd=/opt/atlassian/pipelines/agent/build)

这源于 npm 在 运行 以 root 用户身份 运行 时拒绝 运行 安装后脚本(如果你考虑一下,这对大多数情况来说都是有意义的)。它会尝试更改用户,这会导致您看到关于“cannot 运行 in...”的问题:

https://manpages.ubuntu.com/manpages/focal/en/man7/npm-scripts.7.html#user

If npm was invoked with root privileges, then it will change the uid to the user account or uid specified by the user config, which defaults to nobody. Set the unsafe-perm flag to run scripts with root privileges.

我认为发生的情况是:

  • 您的安装后脚本未执行
  • 不会调用 Ngcc 来预编译模块
  • 出于某种原因测试使用 JIT 编译(我不太清楚为什么)
  • “'not-existing-component' 不是已知元素”- 警告变为错误。
  • 管道失败。

解决方案

详见

您有两个选择:

  1. 添加 --unsafe-perm
  2. 在 Dockerfile 中创建用户并切换到它