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:
- 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)
})
})
- 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')
}
})