如何捕获测试中可观察订阅抛出的异常

问题描述 投票:0回答:1

我不确定如何在Angular 6中使用URL参数处理异常。现在,当找不到URL id时,我的服务会抛出Error。在实际的应用程序中,我喜欢错误气泡被捕获并记录,但在我的茉莉花测试中导致测试失败:

HeroDetailComponent should navigate to not found page
[object ErrorEvent] thrown

我已经尝试了各种try {} catch () {}块和catchError管道来处理茉莉花中的错误,但是在测试期望运行后似乎没有任何东西能够捕获此错误。

该问题的演示:https://angular-observable-catch.stackblitz.io/

请注意,在stackblitz上,测试不会失败,但是当使用ng test在我的应用程序中运行时,它会在本地执行。

在(主)控制台中注意错误:

Uncaught Error: Hero 999 not found.
    at HeroService.getHeroById (hero.service.ts:33)
    at SwitchMapSubscriber.eval [as project] (hero-detail.component.ts:46)
    at SwitchMapSubscriber._next (switchMap.ts:103)
    at SwitchMapSubscriber.Subscriber.next (Subscriber.ts:104)
    at ReplaySubject.Subject.next (Subject.ts:62)
    at ReplaySubject.nextInfiniteTimeWindow (ReplaySubject.ts:42)
    at ActivatedRouteStub.setParamMap (activated-route-stub.ts:56)
    at UserContext.eval (hero-detail.component.spec.ts:65)
    at ZoneDelegate.invoke (zone.js:388)
    at ProxyZoneSpec.onInvoke (zone-testing.js:288)

演示的源代码:https://stackblitz.com/edit/angular-observable-catch?file=src%2Fapp%2Fhero%2Fhero-detail.component.spec.ts

如何在我的茉莉花测试中捕获此错误,以便它不会导致未捕获的错误?


更新

我发现这是由AsyncPipe subscription引起的,它会抛出Observable / Promise /等的任何错误。

angular jasmine observable
1个回答
0
投票

我找到的解决此问题的方法是将TestBed中的AsyncPipe替换为不会抛出错误的AsyncPipe。

测试异步pipe.ts:

import { AsyncPipe } from '@angular/common';
import { Pipe } from '@angular/core';

/**
 * When the AsyncPipe throws errors Jasmine cannot catch them and causes tests to fail.
 * For tests just log the error and move on.
 * Add this class to the TestBed.configureTestingModule declarations.
 */
@Pipe({name: 'async', pure: false}) // tslint:disable-line:use-pipe-transform-interface
export class TestAsyncPipe extends AsyncPipe {
  transform(obj: any): any {
    const ret = super.transform(obj);
    const handleError = (err: any) => { console.error('AsyncPipe Template Exception', err); };
    // @ts-ignore: patch the Observable error handler to not throw an error in tests.
    this._subscription.destination._error = handleError;
    // What if the subscription is a Promise?
    return ret;
  }
}

A-test.spec.ts

import { async, TestBed } from '@angular/core/testing';

import { TestAsyncPipe } from '../testing/test-async-pipe';

import { TestComponent} from './test.component';

describe('TestComponent', () => {
  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [ TestAsyncPipe, TestComponent],
    })
    .compileComponents();
  }));
});
© www.soinside.com 2019 - 2024. All rights reserved.