How to mock Angular 4.3 httpClient an error response in testing

Sai Ram Gupta :

I have a 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 am trying to mock the http.get to throw the error, so that method handleError consoles the 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();
        }))
    );
});

When flushing the response, I am not sure how to flush a error response, so that the method handleError will be called in my interceptor and that eventually calls console.error. Documentation doesn't have any example to my situation. Any help or suggestion is appreciated.

Rohit Sharma :

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

both successful and unsuccessful responses.

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

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

http = TestBed.get(HttpTestingController);
let response: any;
let errResponse: any;
const mockErrorResponse = { status: 400, 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 writing this comment, statusText is required in mockErrorResponse. Related info can be found here.

P.S.: The error method of TestRequest class can be used to simulate network error in our test case, as it expects an instance of Error. The following code snippet shows that.

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

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

In Angular 5 testing, how to mock an http error?

Angular 6 unit testing static mock response

how to mock http error for angular2 testing

How to get HTTP status on error response, while using Angular HttpClient?

Angular 4 testing error

How to Show Response Error body Angular 4

Angular 4 Error: No provider for HttpClient

Angular HttpClient - error response only string

Angular: How to mock MatDialogRef while testing

how to mock an alert in unit testing of angular

Angular 8/httpclient error response for plain/text, cannot parse response

How to get response headers using angular HttpClient

How to mock response from service for testing controller in typescript using Jest

Unit testing - Flurl , How to mock flurl request response?

How to wait and get response for each HttpClient service call from a loop in Angular 4

angular: HttpClient map response

angular4: unable to obtain response string using httpclient get

angular 4 httpclient - type of http response object not enforced by interface

Display Angular4 Response Data From httpClient Iteration ngFor

Angular 5 (Karma / Jasmine Testing) - Using a mock backend to mock error responses for error messages

How to Mock MVC4 application when UI testing with Watin?

Angular2/testing: how to run test with mock service provider?

How to mock a observable stream while testing angular2 components?

How to mock AWS amplify methods in Angular unit testing

How to mock an activatedRoute parent Route in angular2 for testing purposes?

How to mock/spy an imported function in Angular unit testing

How to mock a service call in a function in angular unit testing?

How to mock jquery ajax call while testing angular page

How to mock an @injected service when testing an angular 2 component?