Tutorial

How To Test HttpClient Requests in Angular

Updated on June 16, 2021
author

Alligator.io

How To Test HttpClient Requests in Angular

Introduction

Angular’s HttpClient has a testing module, HttpClientTestingModule, that makes it possible for you to unit test HTTP requests.

Note: Since HttpClient is available only starting with Angular 4.3, the following applies to Angular 4.3+. Consult this introduction if you’re new to unit testing in Angular.

In this article, you will learn how to set up unit tests for an HTTP GET request using the HttpClientTestingModule. This will help demonstrate the capabilities of the testing module.

Prerequisites

To complete this tutorial, you will need:

This tutorial was verified with Node v16.2.0, npm v7.15.1, and @angular/core v12.0.4.

Step 1 — Setting Up the Project

For this post, we’ll be working with a service that gets data from an endpoint and a component that calls that service to populate a list of users in the component’s OnInit hook.

You can use @angular/cli to create a new project:

  1. ng new angular-httpclienttest-example

Then, navigate to the newly created project directory:

  1. cd angular-httpclienttest-example

Create a data.service.ts:

  1. ng generate service data

And have it communicate with JSON Placeholder:

src/app/data.service.ts
import { Injectable } from '@angular/core';
import { HttpClient, HttpRequest } from '@angular/common/http';

@Injectable({ ... })
export class DataService {
  url = 'https://jsonplaceholder.typicode.com/users';

  constructor(private http: HttpClient) { }

  getData() {
    const req = new HttpRequest('GET', this.url, {
      reportProgress: true
    });

    return this.http.request(req);
  }
}

Then, modify the app.component.ts file:

src/app.component.ts
import { Component, OnInit } from '@angular/core';
import { HttpEvent, HttpEventType } from '@angular/common/http';

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

@Component({ ... })
export class AppComponent implements OnInit {
  users: any;
  
  constructor(private dataService: DataService) {}
  
  ngOnInit() {
    this.populateUsers();
  }

  private populateUsers() {
    this.dataService.getData().subscribe((event: HttpEvent<any>) => {
      switch (event.type) {
        case HttpEventType.Sent:
          console.log('Request sent!');
          break;
        case HttpEventType.ResponseHeader:
          console.log('Response header received!');
          break;
        case HttpEventType.DownloadProgress:
          const kbLoaded = Math.round(event.loaded / 1024);
          console.log(`Download in progress! ${kbLoaded}Kb loaded`);
          break;
        case HttpEventType.Response:
          console.log('Done!', event.body);
          this.users = event.body;
      }
    });
  }
}

And add the HttpClientmodule to app.module.ts:

src/app.module.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { HttpClientModule } from '@angular/common/http';

import { AppComponent } from './app.component';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    HttpClientModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

At this point, you will have an Angular project with a service and client.

Step 2 — Adding Tests

Now we’ll setup a spec file for our data service and include the necessary utilities to test out the HttpClient requests. On top of HttpClientTestingModule, we’ll also need HttpTestingController, which makes it easy to mock requests:

data.service.spec.ts
import { TestBed, inject } from '@angular/core/testing';
import { HttpEvent, HttpEventType } from '@angular/common/http';
import {
  HttpClientTestingModule,
  HttpTestingController
} from '@angular/common/http/testing';

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

describe('DataService', () => {
  let service: DataService;

  beforeEach(() => {
    TestBed.configureTestingModule({}
      imports: [HttpclientTestingModule],
      providers: [DataService]
    );
    service = TestBed.inject(DataService);
  });
});

We use the inject utility to inject the needed services into our test.

With this in place, we can add our test logic:

data.service.spec.ts
import { TestBed, inject } from '@angular/core/testing';
import { HttpEvent, HttpEventType } from '@angular/common/http';
import {
  HttpClientTestingModule,
  HttpTestingController
} from '@angular/common/http/testing';

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

describe('DataService', () => {
  beforeEach(() => {
    TestBed.configureTestingModule({
      imports: [HttpClientTestingModule],
      providers: [DataService]
    });
  });
  it(
    'should get users',
    inject(
      [HttpTestingController, DataService],
      (httpMock: HttpTestingController, dataService: DataService) => {
        const mockUsers = [
          { name: 'Alice', website: 'example.com' },
          { name: 'Bob', website: 'example.org' }
        ];

        dataService.getData().subscribe((event: HttpEvent<any>) => {
          switch (event.type) {
            case HttpEventType.Response:
              expect(event.body).toEqual(mockUsers);
          }
        });

        const mockReq = httpMock.expectOne(dataService.url);

        expect(mockReq.cancelled).toBeFalsy();
        expect(mockReq.request.responseType).toEqual('json');
        mockReq.flush(mockUsers);

        httpMock.verify();
      }
    )
  );
});

There’s quite a bit going on, so let’s break it down:

  • First we define a couple of mock users that we’ll test against.
  • We then call the getData method in the service that we’re testing and subscribe to returned observable.
  • If the HttpEventType is of type Response, we assert for the response event to have a body equal to our mock users.
  • We then make use of the HttpTestingController (injected in the test as httpMock) to assert that one request was made to the service’s url property. If no request is expected, the expectNone method can also be used.
  • We can now make any number of assertions on the mock request. Here we assert that the request hasn’t been canceled and the response is of type json. Additionally, we could assert the request’s method (GET, POST, …)
  • Next we call flush on the mock request and pass in our mock users. The flush method completes the request using the data passed to it.
  • Finally, we call the verify method on our HttpTestingController instance to ensure that there are no outstanding requests to be made.

For the purposes of this tutorial, you can comment out app.component.spec.ts.

See the result of your testing by running the following command:

  1. ng test

Open the test results in the browser:

Output
1 spec, 0 failures, randomized with seed 26321 DataService should get users

It will display a successful test message.

Conclusion

In this article, you learned how to set up unit tests for an HTTP GET request using the HttpClientTestingModule.

If you’d like to learn more about Angular, check out our Angular topic page for exercises and programming projects.

Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.

Learn more about our products

About the authors
Default avatar
Alligator.io

author

Still looking for an answer?

Ask a questionSearch for more help

Was this helpful?
 
1 Comments


This textbox defaults to using Markdown to format your answer.

You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!

You are testing the service, but, how do you test populateUsers() in the component’s ngOnInit?

It’s quite hard to find good examples on how to test http requests called in ngOnInit to initialize the component…

Many thanks for your example.

Try DigitalOcean for free

Click below to sign up and get $200 of credit to try our products over 60 days!

Sign up

Join the Tech Talk
Success! Thank you! Please check your email for further details.

Please complete your information!

Become a contributor for community

Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.

DigitalOcean Documentation

Full documentation for every DigitalOcean product.

Resources for startups and SMBs

The Wave has everything you need to know about building a business, from raising funding to marketing your product.

Get our newsletter

Stay up to date by signing up for DigitalOcean’s Infrastructure as a Newsletter.

New accounts only. By submitting your email you agree to our Privacy Policy

The developer cloud

Scale up as you grow — whether you're running one virtual machine or ten thousand.

Get started for free

Sign up and get $200 in credit for your first 60 days with DigitalOcean.*

*This promotional offer applies to new accounts only.