【问题标题】:How to test method throwing error inside the handler of observable?如何在可观察的处理程序中测试方法抛出错误?
【发布时间】:2021-11-13 07:08:47
【问题描述】:

我有一个与外部通信的服务类,并且

public login(token: string) {
  const _this = this;

  return this.httpClient
    .post('url', { idToken: token }, 'httpOptions')
    .pipe(
      catchError((error: HttpErrorResponse) => {
        return this.handleCommError(error);
        //return of([new AuthenticateResponse(...)]);
      })
    )
    .subscribe((res: AuthenticateResponse) => {
       ... handle res
    });
}

handleCommError(error: HttpErrorResponse) {
  console.log('trying to handle comm error');
  console.log(error);
  this.handleError(AuthService.CommunicationErrorCode, `Error trying to auth: ${error.error.detail}`);
  return throwError(`Could not Auth. Try again or contact support.`);
}

我已经实现了处理成功响应的测试,并希望在发生通信错误时测试案例。

这是我的测试的样子:

let httpClientSpy: { post: jasmine.Spy };

describe('AuthState', () => {
  let authService: AuthService;

  beforeEach(async () => {
        httpClientSpy = jasmine.createSpyObj('HttpClient', ['post']);
        authService = new AuthService(httpClientSpy as any);
  });

  fit('login should fail due to communication error', () => {
    const err = new HttpErrorResponse({ error: 'Some error' });
    httpClientSpy.post.and.returnValue(throwError(err));

    expect(authService).toBeTruthy();

    authService.loggedIn.subscribe((loggedIn) => {
      console.log(`loggedIn event: ${loggedIn}`);
      expect(loggedIn).toBeFalse();
    });

    expect(() => {
      authService.handleCommError(err);
    }).toThrowError();

    authService.login('3rdPartyToken');
});

测试执行给出了这个错误:

 Error: Expected function to throw an Error.
    at <Jasmine>
    at UserContext.<anonymous> (http://localhost:9876/_karma_webpack_/webpack:/src/app/auth/AuthState.spec.ts:84:8)
    at ZoneDelegate.invoke (http://localhost:9876/_karma_webpack_/webpack:/node_modules/zone.js/dist/zone-evergreen.js:364:1)
    at ProxyZoneSpec.push.QpwO.ProxyZoneSpec.onInvoke (http://localhost:9876/_karma_webpack_/webpack:/node_modules/zone.js/dist/zone-testing.js:292:1)

当我在控制台中看到“尝试处理通信错误”消息时调用了方法“handleCommError”,但不知何故 jasmine 没有看到我的方法引发了错误。

我觉得我遗漏了一些非常基本的东西,但那是什么?

我做错了什么?

我看到了一个类似的问题 (Expect error to be thrown out of next handler of observable, testing Angular with Jasmine),人们建议“你不需要在订阅中抛出错误”,但就我而言,我必须抛出一个错误以避免进一步执行管道中的订阅者。

作为一种选择,我可以将错误转换为“有效”消息并将其作为“.subscribe”的一部分进行处理,但这对我来说并不合适。

【问题讨论】:

  • 顺便说一句,为什么人们建议在 'subscribe' 之前使用 'pipe' 和 'catchError'?我已经从其中一个示例中复制了代码,但真的不明白这样做的价值吗?在 'subscribe' 内部处理 'err' 也可以达到同样的效果...?

标签: angular unit-testing jasmine karma-jasmine


【解决方案1】:

Khm,我想我找到了答案,至少是一个可靠的选项。

我需要将错误处理添加到“订阅”部分:

  .subscribe(
    (res: AuthenticateResponse) => {
      ... handle res
    },
    (err: any) => {
      console.log(`handling error`);
      console.log(err);
      ... handle err
    }
  );

并优雅地处理错误。或者只是重新抛出它,在这种情况下我仍然会回到原来的问题。

阅读参考文章的 cmets,我注意到使用 https://angular.io/api/core/ErrorHandler 的建议......这可能是要走的路......仍然需要弄清楚如何使用它。

【讨论】:

    猜你喜欢
    • 2017-11-25
    • 1970-01-01
    • 2016-04-20
    • 2017-09-04
    • 2017-03-23
    • 1970-01-01
    • 2018-01-13
    • 1970-01-01
    相关资源
    最近更新 更多