Angular Test随机中断:“未捕获的TypeError:您在期望流的位置提供了'undefined'。”

时间:2018-12-27 09:23:10

标签: jasmine rxjs karma-jasmine

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

  

未捕获到的TypeError:您在期望流的位置提供了“未定义”。

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

我逐步浏览了所有规格文件,并让它们自行运行(使用fdescribe)。每个单独的规格文件都通过且没有错误。同时运行它们会导致所描述的损坏。

当然,我的猜测是我们遇到了一个异步问题,因此我花了很多力气去完成所有测试并将每个测试包装在异步环境中。我还检查了每个订阅都在某个时候取消订阅-这是我们的应用程序的情况,但并非总是用于我们的测试。 但是,错误仍然存​​在。

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

我们现在使用茉莉3.3.0,业力v3.1.4和Angular 7.1.3。 一周前,我们进行了茉莉花和角膜的更新,因为我们希望摆脱这个问题。仅有一件事发生了变化:在更新之前,测试不是随机中断的,而是以固定数量的测试进行的(在我们的示例中,639个测试将导致测试失败,638、640、641 ...等将通过; 648)会再次破裂)。我认为这与茉莉花现在使用的随机种子有关。

这是完整的堆栈跟踪:

<!-- 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

2 个答案:

答案 0 :(得分:0)

糟糕,听起来事情变得片状。最近,我们随机闯入了单元测试。您是否一直在不断更新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() => {},一个必需的.compileComponent()

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

我希望这可以帮助您弄清是什么原因导致了片状现象。由于源自RxJS的迭代器问题似乎指向一种测试,该测试依赖于先前测试所设置的状态,因此该测试以Observable形式接收输入。如果此Observable的设置或定义晚于测试执行的时间,则可能会遇到与您描述的问题类似的问题。

答案 1 :(得分:0)

这可能是由Jasmine测试用例的异步执行顺序引起的。在旧版本的Jasmine中,默认情况下,异步执行顺序设置为false。但是在最新版本的Jasmine中,默认情况下,异步执行顺序设置为true

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

解决方案:

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