问题描述
我们有一个中等大小的 Angular 应用程序,目前有大约 700 个单元测试.几周前,完美的测试开始打破.更奇怪的是:运行两次测试会产生不同的结果,即不同的测试可能会中断.在控制台中,我们总是发现错误:
We have a medium sized angular app with currently about 700 unit tests.A few weeks ago, perfectly fine tests started to break. Even stranger: running the tests twice can yield to different results, i.e. different tests may break.In the console, we always find the error :
未捕获的类型错误:您在预期流的位置提供了未定义".
但堆栈跟踪没有提示错误的根源实际位于何处(请参阅本文末尾).堆栈跟踪显示与 mergeMap
运算符的连接,但事实证明,我们在应用程序和测试中都没有使用此运算符.
But the stack trace gives no hint to where the root of the error is actually located (see end of this post). The stack trace shows a connection to the mergeMap
operator, but it turns out that we use this operator no where in our app and nowhere in our tests.
我逐步检查了所有规范文件并让它们自行运行(使用 fdescribe
).每个规范文件都通过而没有错误.将它们一起运行会导致所描述的损坏.
I stepped through all spec files and let them run on their own (with fdescribe
). Every single spec file passes without errors. Running them all together leads to the described breakage.
当然,我的猜测是我们遇到了异步问题,所以我努力完成所有测试,并将每个测试都包装在异步环境中.我还检查了每个订阅都在某个时候被取消订阅 - 我们的应用程序就是这种情况,但我们的测试并不总是如此.但是,错误仍然存在.
Of course my guess was that we were facing an async problem so I took the effort to go through all the tests and wrap each one of them in an async environment. I also checked that every subscription gets unsubscribed at some point - this was the case for our app but not always for our tests.However, the error still persists.
这对我们的项目来说是个大问题.非常欢迎任何建议.也许有人知道找到导致问题的测试部分的方法?
It's a big issue for our project. Any advice is very welcome.Maybe somebody knows a way to locate the part of our tests that is causing the problem?
我们现在使用 jasmine 3.3.0、karma v3.1.4 和 Angular 7.1.3.我们在一周前做了 jasmine 和 angular 的更新,因为我们希望能解决这个问题.只有一件事发生了变化:在更新之前,测试并没有随机中断,而是在固定数量的测试中中断(在我们的例子中,639 次测试会导致测试中断,638、640、641 等会通过;648会再次破裂).我认为这与 jasmine 现在使用的随机种子有关.
We now use jasmine 3.3.0, karma v3.1.4 and Angular 7.1.3.We did the update of jasmine and angular a week ago because we hoped to get rid of the problem. Only one thing changed: before the update, tests didn't break at random but at a fixed number of tests (in our case, 639 Tests would cause a test to break, 638, 640, 641... etc would pass; 648 would break again). I assume it has something to do with the random seed that jasmine is now using.
这是完整的堆栈跟踪:
<!-- 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 版本?
Oooof, sounds like things have turned flaky. We had a run in with random breaking of unit tests recently. Have you been updating your Angular and Karma versions consistently?
我们遇到的是,默认情况下(通过 Angular CLI)设置单元测试的方式发生了变化,并且旧的测试没有以正确的 async
方式运行.
What we ran into is that the way unit tests are setup by default (by the Angular CLI) has changed, and that older tests were not running the proper async
ways.
您看到的错误确实与我们看到的不同,但我确信这是一个值得探索的途径,以消除单元测试设置引入的任何脆弱性.
The error you are seeing does differ from what we saw, but I'm certain this is an avenue worth exploring to remove any flakiness introduced by the unit tests setup.
取自 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()
.
Extra attention for the first beforeEach()
which has an async() => {}
in there, and a required .compileComponent()
.
第二个beforeEach()
是在describe()
的共享上下文中定义和填充component
变量.
The second beforeEach()
is to define and populate the component
variable within the shared context of the describe()
.
我希望这可以帮助您找出导致片状的原因.由于源自 RxJS 的迭代器问题似乎指向依赖于由先前测试设置的状态的测试,在该测试中它以 Observable 的形式接收输入.如果此 Observable 的设置或定义晚于测试执行,您可能会遇到您所描述的问题.
I hope this helps you figure out what is causing the flakiness. As the iterator issue stemming from RxJS seems to be pointing towards a test that is relying on state being set by a previous test, where it receives an input in the form of an Observable. If this Observable is set or defined later than the tests execution, you may be running into issues like the one you're describing.
这篇关于Angular 测试随机中断:“未捕获的类型错误:您在预期流的位置提供了‘未定义’."的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!