角度测试随机中断:"Uncaught TypeError: You provided 'undefined' where a stream was expected."



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

未捕获类型错误:您在需要流的位置提供了"未定义"。

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

我逐步浏览了所有规范文件,并让它们自己运行(使用fdescribe)。每一个等级库文件都会顺利通过。将它们放在一起运行会导致所描述的断裂。

当然,我的猜测是我们面临着一个异步问题,所以我努力完成了所有的测试,并将其中的每一个都封装在异步环境中。我还检查了每个订阅都会在某个时候被取消订阅——我们的应用程序就是这样,但我们的测试并不总是这样。但是,错误仍然存在。

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

我们现在使用jasmine 3.3.0、karma v3.1.4和Angular 7.1.3。我们在一周前更新了茉莉花和angular,因为我们希望解决这个问题。只有一件事发生了变化:在更新之前,测试不是随机中断的,而是在固定数量的测试中中断的(在我们的案例中,639个测试会导致测试中断,638640641……等等会通过;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

哦,听起来事情已经变得不稳定了。最近,我们遇到了一次单元测试随机中断的冲突。你是否一直在更新你的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()
})

额外注意其中具有async() => {}的第一个beforeEach()和所需的.compileComponent()

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

我希望这能帮助你弄清楚是什么导致了片状。由于源于RxJS的迭代器问题似乎指向一个依赖于前一个测试设置的状态的测试,在该测试中,它接收Observable形式的输入。如果这个Observable是在测试执行之后设置或定义的,那么您可能会遇到您所描述的问题。

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

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

解决方案:

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

最新更新