4

I'm pretty new to Angular and Jasmine framework. I've written some api services wrapping HttpClient to make get/post calls and now I want to unit test the get method to ensure it properly catches and throws the right error.

My api.service.ts looks like this:

import { Injectable } from '@angular/core';
import { HttpClient, HttpParams } from '@angular/common/http';
import { Observable } from 'rxjs';
import { throwError } from 'rxjs';
import { catchError } from 'rxjs/operators';

@Injectable({
  providedIn: 'root'
})

export class ApiService {

  constructor(private http: HttpClient) { }

  // simple wrapper to throw error
  handleErrors(error: any) {
    return throwError(error);
  }

  /**
   * Method: get(url, { params })
   */
  get(url: string, params: HttpParams = new HttpParams()): Observable<any> {
    return this.http.get(url, { params })
      .pipe(catchError(this.handleErrors));
  }
}

My api.service.spec.ts looks like below:

import {TestBed, inject, async} from '@angular/core/testing';
import {HttpClientTestingModule, HttpTestingController} from "@angular/common/http/testing";
import {ApiService} from './api.service';
import {HttpClient, HttpErrorResponse, HttpParams} from "@angular/common/http";
import {of} from "rxjs";

describe('ApiService', () => {
  beforeEach(() => TestBed.configureTestingModule({
    imports: [HttpClientTestingModule],
    providers: [ApiService]
  }));

  afterEach(inject([HttpTestingController], (httpMock: HttpTestingController) => {
    httpMock.verify();
  }));

  it('should be created', () => {
    const service: ApiService = TestBed.get(ApiService);
    expect(service).toBeTruthy();
  });

  it('should throw error properly',
    async(
      inject([HttpClient, ApiService], (http: HttpClient, apiService: ApiService) => {
          const err = {status: 404, statusText: 'Not Found'};
          spyOn(http, 'get').and.throwError(JSON.stringify(err))
          apiService.get('testUrl');
          expect(apiService.get).toThrow(JSON.stringify(err));
        }
      )
    )
  );
});

So when I run the test, all I get is a single line of message:

Failed: {"status":404,"statusText":"Not Found"}

It seems it's throwing the right error but the test failed. I'm confused here on how to write the test to know it properly throws the error which will be caught and processed by handleErrors so that I know .pipe(catchError(this.handleErrors)) actually works?

Thanks.

Charles.S
  • 41
  • 1
  • 3

1 Answers1

0

Try this:

expect(error.status).toEqual(404, 'status');
expect(error.error).toEqual(statusText, 'Not Found');
jburtondev
  • 1,011
  • 10
  • 16
  • Also, I know you're new to the framework, but if you learn how to implement http error handling and testing using an interceptor, this is the preferred solution as you can define the error messages once and every request will have errors handled. – jburtondev Nov 01 '18 at 16:52
  • Then you can test this once, instead of in every service you have. – jburtondev Nov 01 '18 at 16:52