如果实现已订阅它,如何测试 Observables 抛出错误(使用 throwError)?

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

假设我有一个带有此 HTML 的 Angular 组件(摘录):

<some-thirdparty-component
    (onClickCallback)="handleChange($event)"

我有一个函数可以处理这个问题。它将其转发到

service.saveSomething
(返回一个 Observable)。够简单的。作为一个包装组件,我需要
subscribe
,因为我显然想让它执行。

  public handleChange(event: any) {
     this.assignmentService.saveSomething(event)
      .pipe(takeUntil(this.ngUnsubscribe)) // additional error handling may be piped here
      .subscribe();
  }

假设我想测试一下。特别是,我想测试错误情况,即当它(又名保存或其他)失败时:

    let dataMock = {};

    it('should throw error', waitForAsync(() => {
      const error = new Error('test error');
      spyOn(service, 'saveSomething').and.returnValue(throwError(error));

      expect(() => {
        component.handleChange(dataMock);
      }).toThrow();

      expect(service.saveSomething).toHaveBeenCalledOnceWith(dataMock);
      expect(toastService.showToast).toHaveBeenCalledOnceWith(/** **/); // an additional error handling in the pipe to test in a different implementation
    }));

问题是测试失败,在此版本中显示“预期函数会抛出异常。”。

当我将其更改为不希望抛出错误时:

      component.handleChange(dataMock);

然后 jasmine 实际上抛出了一个错误,这使得测试失败:

错误:main.js 中测试错误

我已经将它包裹在waitForAsync

中,这在这种情况下通常很有用。

我的猜测是,问题是由于 Observables 的工作方式,抛出异常以异步方式发生。 Observable 错误被转换为 JS

Error

 并被抛出。然而,我无法通过 jasmine 
toThrow
 捕捉到这个,因为它发生在最后,即通过 
waitForAsync
 并且只在那里捕捉到。但现在断言已经太晚了。

此外,我无法公开 Observable(这是通常的方式),因为有人需要以高效的代码进行订阅。只是出于测试原因而暴露它,对我来说似乎也不干净。

有点像先有鸡还是先有蛋的问题...

那么遇到这种情况该怎么办?

angular testing mocking jasmine
1个回答
0
投票
如果我理解您关于可观察量问题的问题,我个人会做类似的事情,关于调用可观察量并在您的代码库中订阅它们以及错误抛出/处理逻辑。

public handleChange(event: any) { this.assignmentService.saveSomething(event) .pipe(takeUntil(this.ngUnsubscribe)) .subscribe({ next: (value: any) => { console.log(value, 'success!!!'); }, error: (err: any) => { console.error('error detected, printing out the output error msg:', err); } }); }
希望我正确理解你的问题,上面的代码是处理可观察值和订阅输出的错误的好方法。如果您的问题与如何处理 jasmin 错误有关,我个人没有使用过 jasmin,但您可以尝试使用此代码来实现它。

希望这有帮助!祝你有美好的一天! :) :) :)

© www.soinside.com 2019 - 2024. All rights reserved.