Ad

Angular HTTP Interceptor Test Fails While The Interceptor Works Fine

I am writing unit tests for an angular-12 application using karma-jasmine. And, I am still blocked in the HTTP interceptor tests. The role of this interceptor is to add a token to the header of any request to the server. It works fine on the browser, the token is added and I get the response from the server. However, the unit test fails and no authorization is found in the header of my request.

Below is the code of my testing file, What can be the problem and how can I fix it?

describe('JwtInterceptor', () => {
  let client: HttpClient;
  let httpTestingController: HttpTestingController;
  let interceptor: JwtInterceptor;
  beforeEach(() => {
    TestBed.configureTestingModule({
      imports: [
        HttpClientTestingModule,
      ],
      providers: [
        JwtInterceptor,
        {
          provide: HTTP_INTERCEPTORS,
          useClass: JwtInterceptor,
          multi: true
        }
      ],
    });
    client = TestBed.inject(HttpClient)
    httpTestingController = TestBed.inject(HttpTestingController);
    interceptor = TestBed.inject(JwtInterceptor);
  });

  it('should be created', () => { /** This test succeed */
    expect(interceptor).toBeTruthy();
  });

  it('should add an Authorization header',() => { /** This is the test that fails */
    client.get('my-api-url')
          .subscribe((response)=>{
            expect(response).toBeTruthy();
          })         
    const httpRequest = httpTestingController.expectOne('my-api-url');
    expect(httpRequest.request.headers.has('Authorization')).toEqual(true);
  });
});
Ad

Answer

Use any of your service methods to make http request. This one it can verify interceptor properly. Also don't forgot to provide apiUrl in the TestBed configuration.

import {TestBed} from '@angular/core/testing';
import {HttpClientTestingModule, HttpTestingController} from '@angular/common/http/testing';
import {HTTP_INTERCEPTORS, HttpClient} from '@angular/common/http';
import {API_URL, JwtInterceptor} from './jwt.interceptor';
import {DataService} from './data.service';

describe('JwtInterceptor', () => {
  let httpClient: HttpClient;
  let httpTestingController: HttpTestingController;
  let service: DataService;
  beforeEach(() => {
    TestBed.configureTestingModule({
      imports: [HttpClientTestingModule],
      providers: [
        DataService,
        {
          provide: HTTP_INTERCEPTORS,
          useClass: JwtInterceptor,
          multi: true
        },
        {
          provide: API_URL,
          useValue: {apiUrl: 'localhost'}
        }]
    });
    httpClient = TestBed.get(HttpClient);
    httpTestingController = TestBed.get(HttpTestingController);
    service = TestBed.get(DataService);
// for localstorage mocking
let store = {};
const mockLocalStorage = {
  getItem: (key: string): string => {
    return key in store ? store[key] : null;
  },
  setItem: (key: string, value: string) => {
    store[key] = `${value}`;
  },
  removeItem: (key: string) => {
    delete store[key];
  },
  clear: () => {
    store = {};
  }
};
spyOn(localStorage, 'getItem').and.callFake(mockLocalStorage.getItem);
spyOn(localStorage, 'setItem').and.callFake(mockLocalStorage.setItem);
spyOn(localStorage, 'removeItem').and.callFake(mockLocalStorage.removeItem);
spyOn(localStorage, 'clear').and.callFake(mockLocalStorage.clear);
});



  afterEach(() => {
    httpTestingController.verify();
  });



  describe('making http calls', () => {
    it('adds authorization header', () => {
      const apiUrl = TestBed.get(API_URL);
      service.getData().subscribe(response => {
        expect(response).toBeTruthy();
      });

  localStorage.setItem('auth_token', 'any auth token here');
  const authToken = localStorage.getItem('auth_token');
  const req = httpTestingController.expectOne(apiUrl + '/getData');
  expect(req.request.headers.has('Authorization')).toEqual(true);
  expect(req.request.headers.get('Authorization')).toEqual(`Bearer ${authToken}`);
  });
 });

});
Ad
source: stackoverflow.com
Ad