Unit Testing of Angular Service with HttpClient

Services are basically used to allow your code to share the common functionality across the application. Services play a vital role in every Angular application and promote the reusability of code. And to verify that our services are working properly or not we need to test it using unit testing.

First and Foremost thing we’ll do is to create the service which is to be used by other parts of your application i.e code.

Creating the New Project

Install angular-cli and create a new project:

    1. npm install -g @angular/cli
  1. ng new angular-service-testing

When you create the project all the dependencies get installed that you are going to be used while testing and there are some important dependencies which we will discuss below:

    • jasmine-core. Jasmine is the framework we are going to use to create our tests. It has a bunch of functionalities to allow us the write different kinds of tests.
    • karma. Karma is a task runner for our tests. It uses a configuration file in order to set the startup file, the reporters, the testing framework, the browser among other things.
  • The rest of the dependencies are mainly reporters for our tests, tools to use karma and jasmine and browser launcher.

Creating and Testing Services

To test the service first we need to create a service component using below command:

“`ng generate service data“`

The above command states that it will generate the new service name dataService.

data.service.ts

import {Injectable} from '@angular/core';
import {HttpClient} from '@angular/common/http';
import {Post} from './models/post.model';

@Injectable({
    providedIn: 'root'
})
export class DataService {
    public ROOT_URl = 'http://jsonplaceholder.typicode.com';

    constructor(private  http: HttpClient) {
    }

    getPostData() {
        return this.http.get<Post[]>(`${this.ROOT_URl}/posts`);
    }
}

So in the above code, we have taken one sample API route on which we are going to hit to get the data, also create on method name getPostData() which will return all the post using the GET request.

data.service.spec.ts

Now in the spec file where we test the service method getPostData().

import { TestBed } from '@angular/core/testing';

import { DataService } from './data.service';

describe('DataService', () => {
  beforeEach(() => TestBed.configureTestingModule({}));

  it('should be created', () => {
    const service: DataService = TestBed.get(DataNewService);
    expect(service).toBeTruthy();
  });
});
    • So Initially, we have all the necessary import statements that provide an environment to run all the angular tests.
    • After that, we see describe which is used to cover all the test cases of this service, We initialize the component under test with its dependencies in the “beforeEach” within the describe scope of the unit test.
  • Now we have TestBeds which is used to configure TestingModule and runs before each test cases. Usually whenever we creating any module or providing any services will comes under TestBeds.

For testing the method using HttpClient, we need to import Httpclient from @angular/common and add it to the TestBed.Configuration.

import {HttpClientModule} from '@angular/common/http';

In beforeEach, we declare the injected version of Data Service in providers and also imports HttpClientModule in imports to use httpClient Service.

describe('DataService', () => {
    let service: DataService;
    beforeEach(() => {
        TestBed.configureTestingModule({
            imports: [HttpClientModule],
            providers: [DataService]
        });
        service = TestBed.get(DataService);
    });

Now we create dummyPosts data that we are going to expect from the route, also we create one model file for the post to provide a specific type to the dummyPosts variable below:

models -> post.model.ts

export interface Post{
    id: number;
    userId: string;
    body: string;
    title: string;
}

data.service.spec.ts

it('be able to retrieve posts from the API bia GET', () => {
const dummyPosts: Post[] = [{
    userId: '1',
    id: 1,
    body: 'Http Client',
    title: 'Testing Angular Service'
    }, {
    userId: '2',
    id: 2,
    body: 'Hello World2',
    title: 'Testing Angular Services'
}];
service.getPost().subscribe(posts => {
    expect(posts.length).toBe(2);
    expect(posts).toEqual(dummyPosts);
});

Here, we subscribe on the method of service getPost()  and first we expect that the length of the posts is 2 or not and in another expect we ensure that the post we get from the route is equal to the dummy posts.

At this point we don’t want to hit the actual HTTP request for the data, So for that, we need to mock the HTTP request and import Httptestingcontroller which comes from the @angular/common/http/testing.

import {HttpTestingController} from '@angular/common/http/testing';

Then we declare an injected version of httpTestingcontroller and include in TestBed.

describe('DataService', () => {
    let service: DataService;
    let httpMock: HttpTestingController;
    beforeEach(() => {
        TestBed.configureTestingModule({
            imports: [HttpClientModule],
            providers: [DataService]
        });
        service = TestBed.get(DataService);
        httpMock = TestBed.get(HttpTestingController);
    });

and, in the test case, we expect the mocking of http request and expected the requested method is GET like shown in the below code.

it('be able to retrieve posts from the API bia GET', () => {
const dummyPosts: Post[] = [{
    userId: '1',
    id: 1,
    body: 'Hello World',
    title: 'testing Angular'
    }, {
    userId: '2',
    id: 2,
    body: 'Hello World2',
    title: 'testing Angular2'
}];
service.getPost().subscribe(posts => {
    expect(posts.length).toBe(2);
    expect(posts).toEqual(dummyPosts);
});
const request = httpMock.expectOne( `${service.ROOT_URl}/posts`);
expect(request.request.method).toBe('GET');
request.flush(dummyPosts);
});

In the end, we add afterEach(),  a method in which we run http.verify() and test our assertion mock like http, basically it ensures that no request is outstanding.

afterEach(() => {
    httpMock.verify();
});

Conclusion: Now after reading this blog we have a brief understanding of how to test service using httpClient with mocking HTTP request.

Thanks For Reading!!!

 
knoldus-advt-sticker

Written by 

Nitin Arora is Software Consultant at Knoldus Software LLP with 6 months of experience. He has done MCA from Banarsidas Chandiwala Institute of Information technology, Delhi(GGSIPU). He has a graduation degree in BCA from Jamia Hamdard. He has a sound knowledge of various programming languages like C, C++, Java, and scala. Also has a deep interest in frontend development like Html, CSS, Angular, Javascript. He is currently working in frontend technologies like Angular, Html, CSS, Bootstrap and Typescript. He is focused, hardworking, team-oriented member and always exploring new Technologies, His hobbies is to play cricket, volleyball, and do coding.

Leave a Reply

Knoldus Pune Careers - Hiring Freshers

Get a head start on your career at Knoldus. Join us!