【问题标题】:Expect to throws actually crashes when used with RXJS catchError与 RXJS catchError 一起使用时,预计会引发实际崩溃
【发布时间】:2019-11-14 07:01:53
【问题描述】:
it('minimal test case', () => {
    expect(() => {
        of(1).pipe(
            map(() => {
                throw new Error('err');
            }),
            catchError(() => {
                throw new Error('new err');
            }),
        ).subscribe();
    }).toThrow();
});

这段代码实际上会导致 Jasmine/Karma 的整个执行崩溃,即使在原始的 Error 堆栈跟踪中导致 Error 内部的 catchError

我认为如果 observable 抛出并且无法处理它应该在它所在的上下文中传播该错误。否则,我无法测试 observable 是否抛出。

这个(Jasmine)测试会产生以下错误:

未捕获的错误:新错误 在 CatchSubscriber.selector (slideshow.directive.spec.ts:224) 在 CatchSubscriber.push.../../node_modules/rxjs/_esm5/internal/operators/catchError.js.CatchSubscriber.error (catchError.js:34) 在 MapSubscriber.push.../../node_modules/rxjs/_esm5/internal/operators/map.js.MapSubscriber._next (map.js:38) 在 MapSubscriber.push.../../node_modules/rxjs/_esm5/internal/Subscriber.js.Subscriber.next (订阅者.js:53) 在 Observable._subscribe (subscribeToArray.js:5) 在 Observable.push.../../node_modules/rxjs/_esm5/internal/Observable.js.Observable._trySubscribe (Observable.js:43) 在 Observable.push.../../node_modules/rxjs/_esm5/internal/Observable.js.Observable.subscribe (Observable.js:29) 在 MapOperator.push.../../node_modules/rxjs/_esm5/internal/operators/map.js.MapOperator.call (map.js:18) 在 Observable.push.../../node_modules/rxjs/_esm5/internal/Observable.js.Observable.subscribe (Observable.js:24) 在 CatchOperator.push.../../node_modules/rxjs/_esm5/internal/operators/catchError.js.CatchOperator.call (catchError.js:18)

TypeError:无法读取未定义的属性“错误” 在 directCallParentKarmaMethod (context.js:270) 在 ContextKarma.error (context.js:155) 在 handleGlobalErrors (adapter.js:176) 在 KarmaReporter.suiteDone (adapter.js:224) 调度时 (jasmine.js:4560) 在 ReportDispatcher.suiteDone (jasmine.js:4531) 在 nodeComplete (jasmine.js:1019) 在 onComplete (jasmine.js:5528) 在 ZoneDelegate.../../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:423) 在 Zone.../../node_modules/zone.js/dist/zone.js.Zone.runTask (zone.js:195)

预期函数会引发异常。 在用户上下文。 (http://localhost:9876/src/app/shared/thumbnail/slideshow.directive.spec.ts?:227:6) 在 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) 在 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) 在 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)

【问题讨论】:

  • 您对正在发生的事情的解释对我来说有点不清楚。你能试着更清楚地解释发生了什么吗?你所说的“崩溃”是什么意思,是什么导致了“崩溃”。您是说toThrow() 导致异常还是使用catchError()?一些澄清会有所帮助。
  • @Narm 已编辑问题。但要点是,即使在 expect().toThrow() 中调用它也会使 Jasmine/Karma 崩溃,并且错误的堆栈跟踪很奇怪。
  • 大部分 observables 都是异步的。所以从订阅回调中抛出不可能传播到当前上下文。您可以通过订阅错误回调来测试 observable 是否抛出,并检查回调是否确实被调用。
  • 就像 Promise 一样,没有办法将异常传播到原始上下文。不要认为它是一个例外。将其视为“错误结果”。相应地测试所述结果。
  • @cwharris 把它变成一个答案,我会接受,因为它是我问题的答案。

标签: angular unit-testing rxjs jasmine karma-jasmine


【解决方案1】:

一种可能的解决方案是将错误重定向到成功路径,然后测试该值。当被测流的逻辑连接到抛出不同的错误类型时,这可能很有用(尽管在这种情况下,对instanceof Error 的测试当然是不够的)。

  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);
      });
  });

但更常见的方法 afaik 是测试是否调用了正确的回调,如 JB Nizet 所述。例如。你的服务有一个handleError 方法,当流错误时应该调用它。

【讨论】:

  • 我的问题是我无法访问 observable,因为它是事件处理程序的副作用。我所做的不是再次抛出错误,而是登录到 LoggerService 并监视了 .logError 方法。
猜你喜欢
  • 1970-01-01
  • 2021-12-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-06-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多