angularrxjsts-jestangular-http-interceptorsangular-unit-test

Unit testing Angular interceptor without Testbed using Jest. How to check headers were appended with bearer token. [Subscription returns nothing]


So I'm attempting to unit test my interceptor with out using testbed. The interceptor merely appends the Auth headers with a bearer token. I can't seem to figure out how to actually check that those headers have been appended. When subscribe to the interceptor returning the observable next.handle() I get nothing as a response, further to that all code in the subscribe block doesn't execute. I'm using Angular version 15.2.2 and Jest 28.1.3 and RxJs 7.5.6.

Interceptor

intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
if (this.authService.isLoggedIn()) {
  return this.authService.acquireToken().pipe(
    switchMap((data: any) => {
      if (data !== null) {
        let updatedRequest: HttpRequest<any>;
        const authToken = data.accessToken;
        updatedRequest = request.clone({
          setHeaders: {
            Authorization: `Bearer ${authToken}`,
          },
        });
        updatedRequest.headers.append('Authorization', `Bearer ${authToken}`);
        return next.handle(updatedRequest);
      }
    })
  );
} else {
  return EMPTY;
}

Unit test

it('[Intercept] Should intercept the API requests and append auth token if user logged in', (done: DoneCallback) => {
const next: any = {
  handle: () => {
    return Observable.create((subscriber) => {
      subscriber.complete();
    });
  },
};
const requestMock = new HttpRequest('GET', '/test');
const y = interceptor.intercept(requestMock, next).pipe(
  map((r) => r),
  catchError(() => throwError('err')),
  take(1),
  finalize(() => {
    done();
  })
);
y.subscribe((i) => {
  console.log('API call intercepted'), console.log(requestMock.headers);
});

});

Any help would be appreciated because I'm totally lost! Thanks all.


Solution

  •  updatedRequest.headers.append('Authorization', `Bearer ${authToken}`);
    

    This line won't modify updatedRequest.headers, it will create new HttpHeaders instance instead.

    The code inside subscribe is not executed because the Observable never emits any value, it just completes immediately.

    This is how I test similar interceptor in my application:

    it('should add authorization header', () => {
    
        // interceptor depends on AuthStateService
        authStateService.setState({
          token: 'fake-token'
        })
    
        const next: HttpHandler = {
          handle: () => {
            return new Observable((subscriber: Subscriber<any>) => {
              subscriber.complete();
            });
          }
        };
        const requestMock = new HttpRequest('GET', '/test');
    
        spyOn(next, 'handle').and.callThrough();
    
        tokenInterceptor.intercept(requestMock, next).subscribe();
    
        expect(next.handle).toHaveBeenCalledWith(requestMock.clone({
          headers: requestMock.headers.append('Authorization', `Bearer fake-token`)
        }))
    
      });