現在、約 700 のユニット テストがある中規模の Angular アプリがあります。数週間前、まったく問題のないテストが壊れ始めました。さらに奇妙なことに、テストを 2 回実行すると異なる結果になる可能性があり、つまり、異なるテストが壊れる可能性があります。コンソールには、常に次のエラーが表示されます。
キャッチされない TypeError: ストリームが予想される場所に 'undefined' が指定されました。
しかし、スタック トレースは、エラーの根本が実際にどこにあるのかについてのヒントを与えません (この投稿の最後を参照)。スタック トレースは演算子への接続を示していますmergeMap
が、この演算子はアプリのどこにも、またテストのどこにも使用されていないことが判明しました。
すべての仕様ファイルをステップ実行し、それらを単独で実行しました ( を使用fdescribe
)。すべての仕様ファイルはエラーなしで通過します。それらをすべて一緒に実行すると、説明した破損が発生します。
もちろん、非同期の問題に直面しているのではないかと推測したので、すべてのテストを調べて、それぞれを非同期環境にラップする作業を行いました。また、すべてのサブスクリプションがどこかの時点で登録解除されることも確認しました。これはアプリの場合は当てはまりましたが、テストの場合は必ずしも当てはまりませんでした。ただし、エラーは依然として解決しません。
これは私たちのプロジェクトにとって大きな問題です。アドバイスをいただければ幸いです。問題の原因となっているテストの部分を見つける方法を知っている人はいませんか?
現在、Jasmine 3.3.0、Karma v3.1.4、Angular 7.1.3 を使用しています。この問題を解決するために、1 週間前に Jasmine と Angular を更新しました。変更されたのは 1 つだけです。更新前は、テストがランダムに中断されるのではなく、一定数のテストで中断されていました (このケースでは、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
ベストアンサー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() => {}
、 が必須であることに注意してください.compileComponent()
。
2 番目は、の共有コンテキスト内で変数をbeforeEach()
定義して設定することです。component
describe()
これが不安定さの原因を解明する助けになれば幸いです。RxJS に起因するイテレータの問題は、以前のテストによって設定された状態に依存しているテストを指しているようです。このテストでは、Observable の形式で入力を受け取ります。この Observable がテストの実行よりも後で設定または定義されている場合、説明しているような問題が発生する可能性があります。