How to mock Angular 4.3 httpClient test error response

I have below interceptor auth-interceptor.service.ts

 import {Injectable, Injector} from '@angular/core'; import {HttpErrorResponse, HttpEvent, HttpHandler, HttpInterceptor, HttpRequest} from '@angular/common/http'; import {Observable} from 'rxjs/Observable'; import {Cookie} from './cookie.service'; import {Router} from '@angular/router'; import {UserService} from './user.service'; import {ToasterService} from '../toaster/toaster.service'; import 'rxjs/add/operator/catch'; import 'rxjs/add/observable/throw'; @Injectable() export class AuthInterceptor implements HttpInterceptor { constructor(private injector: Injector) {} private handleError(err: HttpErrorResponse): Observable<any> { let errorMsg; if (err.error instanceof Error) { // A client-side or network error occurred. Handle it accordingly. errorMsg = `An error occurred: ${err.error.message}`; } else { // The backend returned an unsuccessful response code. // The response body may contain clues as to what went wrong, errorMsg = `Backend returned code ${err.status}, body was: ${err.error}`; } if (err.status === 401 || err.status === 403) { this.injector.get(UserService).purgeAuth(); this.injector.get(ToasterService).showError(`Unauthorized`, errorMsg); this.injector.get(Router).navigateByUrl(`/login`); } console.error(errorMsg); return Observable.throw(errorMsg); } intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> { // Clone the request to add the new header. const authReq = req.clone({headers: req.headers.set(Cookie.tokenKey, Cookie.getToken())}); // Pass on the cloned request instead of the original request. return next.handle(authReq).catch(err => this.handleError(err)); } } 

Now I'm trying to make fun of http.get to throw an error, so that the handleError method handleError an error message.

Below is my approach to the test case auth-interceptor.service.specs.ts

 import {async, inject, TestBed} from '@angular/core/testing'; import {AuthInterceptor} from './auth-interceptor.service'; import {ApiService} from './api.service'; import {HttpClientTestingModule, HttpTestingController} from '@angular/common/http/testing'; import {environment} from '../../../environments/environment'; describe(`AuthInterceptor`, () => { const somePath = `/somePath`; beforeEach(() => { TestBed.configureTestingModule({ imports: [HttpClientTestingModule], providers: [AuthInterceptor, ApiService] }); }); it(`should be created`, inject([AuthInterceptor], (service: AuthInterceptor) => { expect(service).toBeTruthy(); })); it(`should log an error to the console on error on get()`, async(inject([ApiService, HttpTestingController], (apiService: ApiService, httpMock: HttpTestingController) => { spyOn(console, 'error'); apiService.get(somePath).subscribe((res) => { console.log(`in success:`, res); }, (error) => { console.log(`in error:`, error); }); const req = httpMock.expectOne(`${environment.apiUri}${somePath}`); req.flush({ type: 'ERROR', status: 404, body: JSON.stringify({color: `blue`}) }); expect(console.error).toHaveBeenCalled(); })) ); }); 

While clearing the answer, I am not sure how to reset the error response, so the handleError method will be called on my interceptor and eventually will call console.error . The documentation has no example for my situation. Any help or suggestion appreciated.

+5
source share
1 answer

The expectOne method in the HttpTestingController class returns a TestRequest object. This TestRequest class has a flush method that can be used to deliver

both successful and unsuccessful answers.

We can resolve the request by returning the body along with some additional response headers (if any). Relevant information can be found here .

Now, back to the point, how can you do this. You can customize the code snippet below according to your use case.

 http = TestBed.get(HttpTestingController); let response:any; let errResponse: any; const mockErrorResponse = { status: 404, statusText: 'Bad Request' }; const data = 'Invalid request parameters'; apiService.get(somePath).subscribe(res => response=res, err => errResponse=err); http.expectOne('url/being/monitored').flush(data, mockErrorResponse); expect(errResponse).toBe(data); 

NOTE At the time of this writing, statusText is required in mockErrorResponse . Related information can be found here .

PS . The error method of the TestRequest class can be used to model a network error in our test case, since it expects an Error instance. The following code snippet shows that.

 http.expectOne(someUrl).error(new ErrorEvent('network error')); 
+7
source

Source: https://habr.com/ru/post/1271483/


All Articles