Unit testing HttpInterceptor from Angular 4

Viewed 25050

Can you tell me how to test the HttpInterceptor provided by the Angular 4. I have created an interceptor as per the examples but not sure how to test it. Below is my interceptor and I want to test if the custom headers are added and when response status is 401 window.location.href is done.

export class MyInterceptor implements HttpInterceptor {

    intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
        const headers = new HttpHeaders();
        this.addHeader(headers); // This will add headers

        const changedReq = req.clone({ headers: headers });
        return next.handle(req)
            .catch(err => {
                if (err instanceof HttpErrorResponse) {
                    switch (err.status) {
                        case 302:
                        case 401:
                            window.location.href = "http//google.com";
                            break;             
                        default:
                            throw new Error(this.getErrorMessage(err));
                    }
                }

                return Observable.throw(err);
            });
    }
5 Answers

I got stuck testing a similar thing, but thanks to Alisa's article Intercepting HTTP Requests I got it to work

    import {TestBed, inject} from '@angular/core/testing';
    import {HttpClientTestingModule, HttpTestingController} from '@angular/common/http/testing';
    import {HTTP_INTERCEPTORS, HttpClient} from '@angular/common/http';

    import {LangInterceptorService} from './lang-interceptor.service';

    describe('Lang-interceptor.service', () => {
       beforeEach(() => TestBed.configureTestingModule({
             imports: [HttpClientTestingModule],
             providers: [{
                         provide: HTTP_INTERCEPTORS,
                         useClass: LangInterceptorService,
                         multi: true
              }]
       }));

       describe('intercept HTTP requests', () => {
            it('should add Accept-Language to Headers', inject([HttpClient, HttpTestingController],
              (http: HttpClient, mock: HttpTestingController) => {

                   http.get('/api').subscribe(response => expect(response).toBeTruthy());
                   const request = mock.expectOne(req => (req.headers.has('Accept-Language') && req.headers.get('Accept-Language') === 'ar'));

                   request.flush({data: 'test'});
                   mock.verify();
             }));
        });

        afterEach(inject([HttpTestingController], (mock: HttpTestingController) => {
             mock.verify();
        }));
    });

Just make any call and mock the response with .error() method of HttpTestingController and it should work.

describe('Error interceptor', function () {
let http: HttpTestingController;
  let httpClient: HttpClient;

  beforeEach(() => {
    const testBed = TestBed.configureTestingModule({
      imports: [HttpClientTestingModule],
      providers: [
        {
          provide: HTTP_INTERCEPTORS,
          useClass: MyInterceptor,
          multi: true
        }
      ],
    });

 http = testBed.get(HttpTestingController);
 httpClient = testBed.get(HttpClient);
 });

  it('should catch 401', function (done) {
    httpClient.get('/error').subscribe(() => {}, () => {
      // Perform test
      done();
    });

    http.expectOne('/error').error(new ErrorEvent('Unauthorized error'), {
      status: 401
    });
    http.verify();
  });

});

I wanted to get the response from the request modified by the interceptor, so I used the callback method of the handle object.

Test:

it("should set header authorization", async(() => {
    const token: string = "token_value";        

    let response: HttpResponse<any>;

    const next: any = {
      handle: responseHandle => {
        response = responseHandle;
      }
    };

    const request: HttpRequest<any> = new HttpRequest<any>("GET", `${API_URL}`);

    tokenInterceptor.intercept(request, next);

    expect(response.headers.get("Authorization")).toEqual(token);
}));

I also used a service mock that generates the token to control the value I wanted to validate.

Related