【问题标题】:Angular Tests break at random: "Uncaught TypeError: You provided 'undefined' where a stream was expected."Angular 测试随机中断:“未捕获的 TypeError:您在预期流的位置提供了‘未定义’。”
【发布时间】:2018-12-27 09:23:09
【问题描述】:

我们有一个中等大小的 Angular 应用程序,目前有大约 700 个单元测试。 几周前,完美的测试开始打破。更奇怪的是:运行两次测试会产生不同的结果,即不同的测试可能会中断。 在控制台中,我们总是发现错误:

未捕获的类型错误:您在预期流的位置提供了“未定义”。

但是堆栈跟踪没有提示错误的根源实际位于何处(请参阅本文末尾)。堆栈跟踪显示与 mergeMap 运算符的连接,但事实证明,我们在应用程序和测试中都没有使用此运算符。

我浏览了所有规范文件并让它们自行运行(使用fdescribe)。每个规范文件都通过而没有错误。将它们一起运行会导致所描述的损坏。

当然,我的猜测是我们遇到了异步问题,所以我努力完成所有测试并将每个测试都包装在异步环境中。我还检查了每个订阅都在某个时候被取消订阅 - 我们的应用程序就是这种情况,但我们的测试并不总是如此。 但是,错误仍然存​​在。

这对我们的项目来说是个大问题。非常欢迎任何建议。 也许有人知道找到导致问题的测试部分的方法?

我们现在使用 jasmine 3.3.0、karma v3.1.4 和 Angular 7.1.3。 我们在一周前做了 jasmine 和 angular 的更新,因为我们希望能解决这个问题。只有一件事发生了变化:在更新之前,测试不是随机中断,而是在固定数量的测试中中断(在我们的例子中,639 次测试会导致测试中断,638、640、641 等会通过;648会再次破裂)。我认为这与 jasmine 现在使用的随机种子有关。

这是完整的堆栈跟踪:

<!-- language: lang-none -->
Uncaught TypeError: You provided 'undefined' where a stream was expected. You can provide an Observable, Promise, Array, or Iterable.
    at subscribeTo (:9876/_karma_webpack_/webpack:/node_modules/rxjs/_esm5/internal/util/subscribeTo.js:41)
    at subscribeToResult (:9876/_karma_webpack_/webpack:/node_modules/rxjs/_esm5/internal/util/subscribeToResult.js:11)
    at MergeMapSubscriber.push../node_modules/rxjs/_esm5/internal/operators/mergeMap.js.MergeMapSubscriber._innerSub (:9876/_karma_webpack_/webpack:/node_modules/rxjs/_esm5/internal/operators/mergeMap.js:74)
    at MergeMapSubscriber.push../node_modules/rxjs/_esm5/internal/operators/mergeMap.js.MergeMapSubscriber._tryNext (:9876/_karma_webpack_/webpack:/node_modules/rxjs/_esm5/internal/operators/mergeMap.js:68)
    at MergeMapSubscriber.push../node_modules/rxjs/_esm5/internal/operators/mergeMap.js.MergeMapSubscriber._next (:9876/_karma_webpack_/webpack:/node_modules/rxjs/_esm5/internal/operators/mergeMap.js:51)
    at MergeMapSubscriber.push../node_modules/rxjs/_esm5/internal/Subscriber.js.Subscriber.next (:9876/_karma_webpack_/webpack:/node_modules/rxjs/_esm5/internal/Subscriber.js:54)
    at Observable._subscribe (:9876/_karma_webpack_/webpack:/node_modules/rxjs/_esm5/internal/util/subscribeToArray.js:5)
    at Observable.push../node_modules/rxjs/_esm5/internal/Observable.js.Observable._trySubscribe (:9876/_karma_webpack_/webpack:/node_modules/rxjs/_esm5/internal/Observable.js:43)
    at Observable.push../node_modules/rxjs/_esm5/internal/Observable.js.Observable.subscribe (:9876/_karma_webpack_/webpack:/node_modules/rxjs/_esm5/internal/Observable.js:29)
    at MergeMapOperator.push../node_modules/rxjs/_esm5/internal/operators/mergeMap.js.MergeMapOperator.call (:9876/_karma_webpack_/webpack:/node_modules/rxjs/_esm5/internal/operators/mergeMap.js:29)
    at ____________________Elapsed_3_ms__At__Thu_Dec_27_2018_10_03_35_GMT_0100__Mitteleurop_ische_Normalzeit_ ()
    at Object.onScheduleTask (:9876/_karma_webpack_/webpack:/node_modules/zone.js/dist/zone-testing.js:108)
    at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.scheduleTask (:9876/_karma_webpack_/webpack:/node_modules/zone.js/dist/zone.js:401)
    at Object.onScheduleTask (:9876/_karma_webpack_/webpack:/node_modules/zone.js/dist/zone.js:297)
    at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.scheduleTask (:9876/_karma_webpack_/webpack:/node_modules/zone.js/dist/zone.js:401)
    at Zone.push../node_modules/zone.js/dist/zone.js.Zone.scheduleTask (:9876/_karma_webpack_/webpack:/node_modules/zone.js/dist/zone.js:232)
    at Zone.push../node_modules/zone.js/dist/zone.js.Zone.scheduleMacroTask (:9876/_karma_webpack_/webpack:/node_modules/zone.js/dist/zone.js:255)
    at scheduleMacroTaskWithCurrentZone (:9876/_karma_webpack_/webpack:/node_modules/zone.js/dist/zone.js:1114)
    at :9876/_karma_webpack_/webpack:/node_modules/zone.js/dist/zone.js:2090

【问题讨论】:

  • 您是否也搜索过flatMap 的出现,它只是mergeMap 的别名,因此我可以想象堆栈跟踪中说明了这一点?
  • 您必须提供一些代码,然后我们才能找出问题所在!

标签: jasmine rxjs karma-jasmine


【解决方案1】:

哎呀,听起来事情变得不稳定了。我们最近遇到了随机破坏单元测试的情况。您是否一直在更新您的 Angular 和 Karma 版本?

我们遇到的是,默认情况下(通过 Angular CLI)设置单元测试的方式发生了变化,并且旧的测试没有以正确的async 方式运行。

您看到的错误确实与我们看到的不同,但我确信这是一个值得探索的途径,以消除单元测试设置引入的任何脆弱性。

取自https://angular.io/guide/testing#calling-compilecomponents

describe('BannerComponent', () => {
    let component: BannerComponent
    let fixture: ComponentFixture<BannerComponent>

    beforeEach(async(() => {
      TestBed.configureTestingModule({
        declarations: [ BannerComponent ],
      }).compileComponents();  // compile template and css
    }));

    beforeEach(() => {
        fixture = TestBed.createComponent(BannerComponent)
        component = fixture.componentInstance
        fixture.detectChanges()
    })

    it('should create', () => {
        expect(component).toBeTruthy()
    })

特别注意第一个beforeEach(),其中有一个async() =&gt; {},以及一个必需的.compileComponent()

第二个beforeEach() 是在describe() 的共享上下文中定义和填充component 变量。

我希望这可以帮助您找出导致片状的原因。由于源自 RxJS 的迭代器问题似乎指向依赖于由先前测试设置的状态的测试,其中它以 Observable 的形式接收输入。如果此 Observable 的设置或定义晚于测试执行,您可能会遇到您所描述的问题。

【讨论】:

  • 注意:在 Angular 10.1.0 中,waitForAsync() 已替换 async()
【解决方案2】:

可能是 Jasmine 测试用例执行顺序不同步造成的。在 Jasmine 的旧版本中,异步执行顺序默认设置为 false。但是在最近的 Jasmine 版本中,异步执行顺序默认设置为true

主要原因:变量已在此测试用例之前执行的其他测试用例中被覆盖。

解决方案:

  1. 我们需要找出为什么我们的变量会得到undefined。在抛出undefined 的语句上方放置一个控制台。使用 beforeEach 重新初始化该变量。
  2. 在您的 karma.config.js 前将 random 设置为 falsehttps://github.com/karma-runner/karma-jasmine

【讨论】:

    猜你喜欢
    • 2022-01-17
    • 2020-03-10
    • 2021-09-10
    • 2021-12-10
    • 1970-01-01
    • 2018-09-07
    • 2018-11-08
    • 2021-05-21
    • 2018-05-31
    相关资源
    最近更新 更多