Angular 7: Test Error Interceptor
Testing an error interceptor can be a little tricky. Below is the code I want to test :
Basically we need to perform an HTTP request and respond with a mocking error for testing this interceptor. You need also to register it in the
Thanks for sharing...
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Injectable } from '@angular/core'; | |
import { HttpRequest, HttpHandler, HttpEvent, HttpInterceptor, HttpErrorResponse } from '@angular/common/http'; | |
import { Observable, throwError } from 'rxjs'; | |
import { catchError } from 'rxjs/operators'; | |
import { AuthenticationService } from './../services/authentication.service'; | |
@Injectable() | |
export class ErrorInterceptor implements HttpInterceptor { | |
constructor(private authenticationService: AuthenticationService) { } | |
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> { | |
return next.handle(request).pipe(catchError((err: HttpErrorResponse) => { | |
if (err.error instanceof ErrorEvent) { | |
//TODO : add server log for client errors | |
} else { | |
if ([401, 403].indexOf(err.status) !== -1) { | |
// automatically logout | |
this.authenticationService.logout(); | |
} | |
} | |
const error = err.error || err.statusText; | |
return throwError(error); | |
})) | |
} | |
} |
Basically we need to perform an HTTP request and respond with a mocking error for testing this interceptor. You need also to register it in the
TestBed.configureTestingModule
.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { TestBed } from '@angular/core/testing'; | |
import { | |
HttpClientTestingModule, | |
HttpTestingController | |
} from '@angular/common/http/testing'; | |
import { HTTP_INTERCEPTORS, HttpClient, HttpErrorResponse } from '@angular/common/http'; | |
import { ErrorInterceptor } from './error.interceptor'; | |
import { AuthenticationService } from '../services/authentication.service'; | |
import { MockAuthService } from './../../testing/services/authentication.service.mock'; | |
const testUrl = '/data'; | |
interface Data { | |
name: string; | |
} | |
describe('ErrorInterceptor', () => { | |
describe('intercept', () => { | |
let errorInterceptor: ErrorInterceptor; | |
let authService: AuthenticationService; | |
let httpClient: HttpClient; | |
let httpMock: HttpTestingController; | |
beforeEach(() => { | |
TestBed.configureTestingModule({ | |
providers: [ErrorInterceptor, | |
{ provide: AuthenticationService, useClass: MockAuthService }, | |
{ | |
provide: HTTP_INTERCEPTORS, | |
useClass: ErrorInterceptor, | |
multi: true, | |
} | |
], | |
imports: [HttpClientTestingModule] | |
}); | |
httpClient = TestBed.get(HttpClient); | |
httpMock = TestBed.get(HttpTestingController); | |
authService = TestBed.get(AuthenticationService); | |
spyOn(authService, 'logout'); | |
errorInterceptor = TestBed.get(ErrorInterceptor); | |
}); | |
it('When 401 or 403, user is automatically logged out and error is rethrow', () => { | |
const emsg = 'deliberate 401 error'; | |
// Make an HTTP GET request | |
httpClient.get<Data>(testUrl).subscribe( | |
res => fail('should have failed with the 401 error'), | |
(error: HttpErrorResponse) => { | |
expect(error).toEqual(emsg, 'message'); | |
} | |
); | |
// The following `expectOne()` will match the request's URL. | |
const req = httpMock.expectOne(testUrl) | |
// Respond with mock error | |
req.flush(emsg, { status: 401, statusText: 'Unauthorized' }); | |
expect(authService.logout).toHaveBeenCalledTimes(1); | |
}); | |
}); | |
}); |
Thanks for sharing...
Comments
Post a Comment