Karma - Chrome Headless - 测试失败 - 抛出未捕获的 null

Karma - Chrome Headless - test FAILED - Uncaught null thrown

虽然 运行 单元测试,它们“有时”会失败,总是在不同的测试中,没有任何有意义的错误。

...
Chrome 89.0.4389.114 (Linux x86_64): Executed 1225 of 1453 SUCCESS (0 secs / 3 mins 29.829 secs)
Chrome 89.0.4389.114 (Linux x86_64): Executed 1226 of 1453 SUCCESS (0 secs / 3 mins 30.893 secs)
Chrome 89.0.4389.114 (Linux x86_64): Executed 1227 of 1453 SUCCESS (0 secs / 3 mins 31.923 secs)
Chrome 89.0.4389.114 (Linux x86_64) ChooseOfWorkplaceComponent should show institutie warning info FAILED
        Uncaught null thrown
Chrome 89.0.4389.114 (Linux x86_64): Executed 1228 of 1453 (1 FAILED) (0 secs / 3 mins 32.237 secs)
    ✗ should show institutie warning info
        Uncaught null thrown
Chrome 89.0.4389.114 (Linux x86_64): Executed 1229 of 1453 (1 FAILED) (0 secs / 3 mins 32.713 secs)
Chrome 89.0.4389.114 (Linux x86_64): Executed 1230 of 1453 (1 FAILED) (0 secs / 3 mins 33.432 secs)
Chrome 89.0.4389.114 (Linux x86_64): Executed 1231 of 1453 (1 FAILED) (0 secs / 3 mins 33.461 secs)

Karma.conf.js:

module.exports = function (config) {
  config.set({
    basePath: '',
    frameworks: ['jasmine', '@angular-devkit/build-angular'],
    plugins: [
      require('karma-jasmine'),
      require('karma-chrome-launcher'),
      require('karma-jasmine-html-reporter'),
      require('karma-coverage'),
      require('karma-spec-reporter'),
      require('@angular-devkit/build-angular/plugins/karma'),
    ],
    client: {
      clearContext: false, // leave FJasmine Spec Runner output visible in browser
      jasmine: {
        random: false,
      },
    },
    jasmineHtmlReporter: {
      suppressAll: true, // removes the duplicated traces
    },
    coverageReporter: {
      dir: require('path').join(__dirname, '...'),
      subdir: '.',
      reporters: [{ type: 'html' }, { type: 'text-summary' }],
      check: {
        global: {
          statements: 50,
          branches: 50, 
          functions: 50,
          lines: 50, 
        },
      },
    },
    captureTimeout: 180000,
    browserNoActivityTimeout: 60000,
    browserDisconnectTimeout: 10000,
    browserDisconnectTolerance: 3,
    reporters: ['progress', 'kjhtml', 'spec'],
    port: 9876,
    colors: true,
    logLevel: config.DEBUG,
    autoWatch: true,
    browsers: ['Chrome', 'ChromeHeadless'],
    singleRun: false,
    restartOnFileChange: true,
    customLaunchers: {
      ChromeHeadlessCI: {
        base: 'ChromeHeadless',
        flags: ['--no-sandbox'],
      },
    },
  });
};

Angular版本:

$ ng --version

     _                      _                 ____ _     ___
    / \   _ __   __ _ _   _| | __ _ _ __     / ___| |   |_ _|
   / △ \ | '_ \ / _` | | | | |/ _` | '__|   | |   | |    | |
  / ___ \| | | | (_| | |_| | | (_| | |      | |___| |___ | |
 /_/   \_\_| |_|\__, |\__,_|_|\__,_|_|       \____|_____|___|
                |___/
    

Angular CLI: 13.2.2
Node: 14.17.1
Package Manager: npm 6.14.13
OS: linux x64

Angular: 13.2.1
... animations, cdk, common, compiler, compiler-cli, core, forms
... localize, material, material-moment-adapter
... platform-browser, platform-browser-dynamic, router

Package                         Version
---------------------------------------------------------
@angular-devkit/architect       0.1302.2
@angular-devkit/build-angular   13.2.2
@angular-devkit/core            13.2.2
@angular-devkit/schematics      13.2.2
@angular/cli                    13.2.2
@angular/flex-layout            12.0.0-beta.35
@schematics/angular             13.2.2
rxjs                            7.4.0
typescript                      4.5.5

另一个错误日志,说明错误是如何随机出现的,没有其他数据:

...
15:42:21  #19 381.2 [1A[2KChrome Headless 93.0.4577.82 (Linux x86_64): Executed 1253 of 1453 SUCCESS (0 secs / 3 mins 29.334 secs)
15:42:21  #19 381.2     [32m✓ [39mshould "toIdentificationMode" anim status
15:42:21  #19 381.3 [1A[2KChrome Headless 93.0.4577.82 (Linux x86_64) ERROR
15:42:21  #19 381.3   An error was thrown in afterAll
15:42:21  #19 381.3   Uncaught null thrown
15:42:21  #19 381.3 Chrome Headless 93.0.4577.82 (Linux x86_64): Executed 1253 of 1453 ERROR (0 secs / 3 mins 29.334 secs)
15:42:21  #19 381.3 Chrome Headless 93.0.4577.82 (Linux x86_64) ERROR
15:42:21  #19 381.3   An error was thrown in afterAll
15:42:21  #19 381.3   Uncaught null thrown
15:42:21  #19 381.3 [31mChrome Headless 93.0.4577.82 (Linux x86_64) ERROR[39m
15:42:21  #19 381.3   An error was thrown in afterAll
15:42:21  #19 381.3   Uncaught null thrown
15:42:21  #19 381.3 [1A[2KChrome Headless 93.0.4577.82 (Linux x86_64): Executed 1253 of 1453 ERROR (4 mins 27.037 secs / 3 mins 29.334 secs)

更新: 我能够在 Chrome window.

中发现错误
zone.js:182 Uncaught null
runTask @ zone.js:182
invokeTask @ zone.js:487
ZoneTask.invoke @ zone.js:476
data.args.<computed> @ zone.js:2541
setTimeout (async)
scheduleTask @ zone.js:2543
scheduleTask @ zone.js:393
onScheduleTask @ zone-testing.js:306
scheduleTask @ zone.js:386
scheduleTask @ zone.js:221
scheduleMacroTask @ zone.js:244
scheduleMacroTaskWithCurrentZone @ zone.js:679
(anonymous) @ zone.js:2585
proto.<computed> @ zone.js:975
setTimeout @ timeoutProvider.js:4
reportUnhandledError @ reportUnhandledError.js:4
(anonymous) @ Subscriber.js:117
_error @ Subscriber.js:64
error @ Subscriber.js:40
_error @ Subscriber.js:64
error @ Subscriber.js:40
init @ throwError.js:5
_trySubscribe @ Observable.js:37
(anonymous) @ Observable.js:31
errorContext @ errorContext.js:19
subscribe @ Observable.js:22
doInnerSub @ mergeInternals.js:19
outerNext @ mergeInternals.js:14
OperatorSubscriber._next @ OperatorSubscriber.js:9
next @ Subscriber.js:31
(anonymous) @ innerFrom.js:51
_trySubscribe @ Observable.js:37
(anonymous) @ Observable.js:31
errorContext @ errorContext.js:19
subscribe @ Observable.js:22
mergeInternals @ mergeInternals.js:50
(anonymous) @ mergeMap.js:13
(anonymous) @ lift.js:10
(anonymous) @ Observable.js:26
errorContext @ errorContext.js:19
subscribe @ Observable.js:22
(anonymous) @ session-transfer.component.ts:263
(anonymous) @ Subscriber.js:110
_complete @ Subscriber.js:72
complete @ Subscriber.js:49
(anonymous) @ take.js:14
OperatorSubscriber._next @ OperatorSubscriber.js:9
next @ Subscriber.js:31
(anonymous) @ map.js:7
OperatorSubscriber._next @ OperatorSubscriber.js:9
next @ Subscriber.js:31
(anonymous) @ timer.js:23
_execute @ AsyncAction.js:53
execute @ AsyncAction.js:41
flush @ AsyncScheduler.js:18
timer @ zone.js:2561
invokeTask @ zone.js:406
onInvokeTask @ zone-testing.js:318
invokeTask @ zone.js:405
runTask @ zone.js:178
invokeTask @ zone.js:487
ZoneTask.invoke @ zone.js:476
data.args.<computed> @ zone.js:2541
Show 32 more frames

我们没有太多,但它可能会帮助别人看看它可能是什么。

对于可能偶然发现此问题的任何人:我能够使用 chrome 的“异常停止”功能捕获错误。在其中我们仍然只看到抛出了一个“null”(并且没有任何 stacttrace),但我们也看到错误发生在 zone.js 任务对象中,它提供了有关导致错误的原因的足够信息。

是我们。抱歉,添麻烦了。我们在其中一个测试中抛出了一个空对象,但没有捕获到它。这是一个非常糟糕的做法。

    if (typeof res === 'boolean') {
          return of(res);
        } else {
          return throwError(res);   // res can be null...
        }

所以最重要的是,要怀疑为什么堆栈跟踪是准确的null...