Reputation: 11475
it('minimal test case', () => {
expect(() => {
of(1).pipe(
map(() => {
throw new Error('err');
}),
catchError(() => {
throw new Error('new err');
}),
).subscribe();
}).toThrow();
});
This code will actually crash the whole execution of Jasmine/Karma, even in the original Error
stacktrace leads to the Error
inside catchError
.
I think that if observable throws and cannot handle it should propagate that error in the context it is in. Otherwise, I cannot test if the observable throws.
This (Jasmine) test will produce following errors:
Uncaught Error: new err at CatchSubscriber.selector (slideshow.directive.spec.ts:224) at CatchSubscriber.push.../../node_modules/rxjs/_esm5/internal/operators/catchError.js.CatchSubscriber.error (catchError.js:34) at MapSubscriber.push.../../node_modules/rxjs/_esm5/internal/operators/map.js.MapSubscriber._next (map.js:38) at MapSubscriber.push.../../node_modules/rxjs/_esm5/internal/Subscriber.js.Subscriber.next (Subscriber.js:53) at Observable._subscribe (subscribeToArray.js:5) at Observable.push.../../node_modules/rxjs/_esm5/internal/Observable.js.Observable._trySubscribe (Observable.js:43) at Observable.push.../../node_modules/rxjs/_esm5/internal/Observable.js.Observable.subscribe (Observable.js:29) at MapOperator.push.../../node_modules/rxjs/_esm5/internal/operators/map.js.MapOperator.call (map.js:18) at Observable.push.../../node_modules/rxjs/_esm5/internal/Observable.js.Observable.subscribe (Observable.js:24) at CatchOperator.push.../../node_modules/rxjs/_esm5/internal/operators/catchError.js.CatchOperator.call (catchError.js:18)
TypeError: Cannot read property 'error' of undefined at directCallParentKarmaMethod (context.js:270) at ContextKarma.error (context.js:155) at handleGlobalErrors (adapter.js:176) at KarmaReporter.suiteDone (adapter.js:224) at dispatch (jasmine.js:4560) at ReportDispatcher.suiteDone (jasmine.js:4531) at nodeComplete (jasmine.js:1019) at onComplete (jasmine.js:5528) at ZoneDelegate.../../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:423) at Zone.../../node_modules/zone.js/dist/zone.js.Zone.runTask (zone.js:195)
Expected function to throw an exception. at UserContext. (http://localhost:9876/src/app/shared/thumbnail/slideshow.directive.spec.ts?:227:6) at ZoneDelegate.../../node_modules/zone.js/dist/zone.js.ZoneDelegate.invoke (http://localhost:9876/C:/Users/uzivatel/Documents/nubium/ulozto-web/angular/node_modules/zone.js/dist/zone.js?:391:1) at ProxyZoneSpec.push.../../node_modules/zone.js/dist/zone-testing.js.ProxyZoneSpec.onInvoke (http://localhost:9876/C:/Users/uzivatel/Documents/nubium/ulozto-web/angular/node_modules/zone.js/dist/zone-testing.js?:289:1) at ZoneDelegate.../../node_modules/zone.js/dist/zone.js.ZoneDelegate.invoke (http://localhost:9876/C:/Users/uzivatel/Documents/nubium/ulozto-web/angular/node_modules/zone.js/dist/zone.js?:390:1)
Upvotes: 0
Views: 1292
Reputation: 388
One possible solution is to redirect the error to the success path, then testing that value. This can be useful when the stream under test has logic connected to throwing different error types (though in such a case a test for instanceof Error
would of course not be sufficient).
it('should be of type error', () => {
of(1)
.pipe(
map(() => {
throw new Error('err');
}),
catchError(error => of(error)))
.subscribe(result => {
expect(result instanceof Error).toBe(true);
});
});
But a more common approach afaik is to test if the correct callback has been called, as mentioned by JB Nizet. E.g. your service has an handleError
method that should be called when a stream errors.
Upvotes: 1