Home > Enterprise >  Angular 13 How to Unit Test Interceptor catchError method
Angular 13 How to Unit Test Interceptor catchError method

Time:05-12

i'm working on an existing Angular Project and i have the following intercepter with Error Handling. this is the code :

public intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
   
    const sendAccessToken = this.moduleConfig.resourceServer.sendAccessToken;
    
    if (sendAccessToken) {
      const token = this.authStorage.getItem('access_token');
      const header = 'Bearer '   token;

      const headers = req.headers.set('Authorization', header);

      req = req.clone({ headers });
    }
    
    return next.handle(req).pipe(
      catchError(err => {
        let errorMessage: string;
        if (err instanceof HttpErrorResponse) {

          switch (err.status) {
            
            case 401: {
              errorMessage = 'Autorisation required.';
              break;
            }

            default: {
              const erreurText = err.error.messages[0].message
              break;
            }
          }
        }

        this.toastr.error(errorMessage);
        const error = err.error;

        return error;

      }),
    ) as any;
  }

and this is my test where i want to trigger the catcherror but i don't know how i can do that :

  it('#should handle incorrect url', () => {
    const requestMock = new HttpRequest('GET', '/wrongtest');
    interceptor.intercept(requestMock, next).subscribe(() => {
      expect(requestMock.headers.has('Authorization')).toEqual(false);
    });
  });

can anyone please guide me how i can trigger the error in my HttpRequest.

thanks in advance.

CodePudding user response:

Assuming you're using jasmine for testing:

  1. Inject all your test dependencies:
// Necessary to inject the right HTTP interceptor
const interceptorOf = <T>(type: Type<T>) =>
  TestBed
    .inject(HTTP_INTERCEPTORS)
    .find(interceptor => interceptor instanceof type) as unknown as T

describe('...', () => {
  let httpClient: HttpClient
  let httpMock: HttpTestingController
  let interceptor: ErrorInterceptor

  beforeEach(async () =>
    await TestBed.configureTestingModule({
      imports: [
        // Load all your interceptor's dependencies
        HttpClientTestingModule,
      ],
      providers: [
        {
          provide: HTTP_INTERCEPTORS,
          deps: [], // Fill with your interceptor's dependencies 
          useClass: ErrorInterceptor,
          multi: true
        },
      ],
    }).compileComponents()
    httpMock = TestBed.inject(HttpTestingController)
    httpClient = TestBed.inject(HttpClient)
    interceptor = interceptorOf(ErrorInterceptor)
  })
})
  1. Call a normal endpoint and mock the response:
it('should do something', async () =>{
    const observable$ = httpClient.get(testUrl)
    const serviceUnavailable = new HttpErrorResponse({
      status: 503,
      statusText: 'Service Unavailable',
      url: testUrl
    })

    const httpReqPromise = firstValueFrom(observable$)
    httpMock.expectOne(testUrl).flush('error', serviceUnavailable)
    
    try {
      await httpReqPromise
      fail('It should have not succeeded')
    } catch(error) {
       expect(error instanceof HttpErrorResponse).toBeTrue()
       expect(error.status).toBe(503)
    }
})

Note 1: Your catchError pipe usage is invalid; you're not supposed to return an error, but an observable that will be used instead of the one that crashed.

catchError(err => {
  ...
  const error = err.error;
  return of(error);
})

Note 2: If you do as I did on the snippet above your error is going to be propagated onto the "next" callback which should resolve the following promise as successful

it('should do something', async () =>{
    const observable$ = httpClient.get(testUrl)
    const serviceUnavailable = new HttpErrorResponse({
      status: 503,
      statusText: 'Service Unavailable',
      url: testUrl
    })

    const httpReqPromise = firstValueFrom(observable$)
    httpMock.expectOne(testUrl).flush('error', serviceUnavailable)
    
    try {
      const error = await httpReqPromise
      expect(error instanceof HttpErrorResponse).toBeTrue()
      expect(error.status).toBe(503)
    } catch(__) {
      fail('It should have not thrown')
    }
})
  • Related