Angular Test HTTP POST
March 04, 2020
This page will walk through Angular unit testing for HTTP POST method using HttpClient.post
. Angular uses Jasmine test framework and Karma test runner to create and run unit test cases. Angular provides HttpClientTestingModule
for testing HTTP requests with HttpClient
class. Using Angular HttpTestingController
we can mock flushing of HTTP requests. Angular provides TestBed
that is the primary API to write Angular tests. The TestBed
configures components and services in application test module and instantiates them handling their dependency injection. Angular test codes are written in .spec.ts
file which name is sibling to actual file and is in same folder. If our actual file is employee.service.ts
then test file will be employee.service.spec.ts
in same folder.
Here on this page we will create example to test a service class which has a method to POST data using
HttpClient.post
method.
Contents
1. Technologies Used
Find the technologies being used in our example.1. Angular 9.0.2
2. Node.js 12.5.0
3. Jasmine Core 3.5.0
4. Karma 4.3.0
2. HttpClientTestingModule
TheHttpClientTestingModule
is the Angular testing module used to test HTTP methods using HttpClient
. The HttpClientTestingModule
injects HttpTestingController
that helps to expect and flush requests in our tests. The HttpClientTestingModule
is imported as following.
import { HttpClientTestingModule } from '@angular/common/http/testing';
3. HttpTestingController
TheHttpTestingController
allows mocking and flushing of HTTP requests. It can be imported as following.
import { HttpTestingController } from '@angular/common/http/testing';
HttpTestingController
provides methods as match
, expectOne
, expectNone
, verify
. In our demo we will use following methods.
1.
abstract verify(opts?: { ignoreCancelled?: boolean; }): void
afterEach(() => { httpTestingController.verify(); });
abstract expectOne(url: string, description?: string): TestRequest
TestRequest
. It is used as following.
const req = httpTestingController.expectOne(empService.empUrl);
req
is the instance of TestRequest
.
TestRequest
The
TestRequest
is a mock request. It has methods as flush
, error
, event
. In our demo we will use its following methods.
1.
flush(body, opts): void
The
flush
is used to resolve the request by returning a body. For example,
const req = httpTestingController.expectOne(empService.empUrl); req.flush(newEmp);
req
is the object of type TestRequest
. When we subscribe the request, the HttpClient
method will return the specified object i.e. newEmp.
2.
event(event: HttpEvent<any>): void
HttpEvent
on the response stream for this request. The HttpEvent
is the type of all possible events on the response stream such as HttpResponse
, HttpHeaderResponse
etc. The event
is used as following.
const expectedResponse = new HttpResponse({ status: 201, statusText: 'Created', body: newEmp }); req.event(expectedResponse);
HttpClient
method will return expectedResponse
.
The
TestRequest
has a request
property of HttpRequest
type that can be used to get request information. For example,
req.request.method
4. TestBed
TheTestBed
is the primary API for writing Angular unit tests. Find some of its methods.
1.
configureTestingModule(moduleDef: TestModuleMetadata): void
TestBed.configureTestingModule({ imports: [HttpClientTestingModule], providers: [ EmployeeService ] });
inject<T>(token: Type<T>, flags?: InjectFlags): T | null
httpClient = TestBed.inject(HttpClient); httpTestingController = TestBed.inject(HttpTestingController); empService = TestBed.inject(EmployeeService);
inject
method injects the dependencies. In the EmployeeService
, its constructor has the dependency of HttpClient
. While instantiating EmployeeService
, the inject
method injects mock HttpClient
.
The
TestBed
is imported as following.
import { TestBed } from '@angular/core/testing';
5. Jasmine Test Framework
Angular test application is created with Jasmine test framework. Jasmine is a JavaScript based test framework. Angular CLI downloads and installs everything required to run Jasmine test in our Angular application. Find the sample code to write Jasmine test.describe("Test name", function() { beforeEach(() => { //TODO }); afterEach(() => { //TODO }); var msg; it("Test description", function() { msg = 'Hello'; expect(msg).toEqual('Hello'); }); });
describe() : Creates a group of specs.
beforeEach() : Executes before each of the specs in the
describe
in which it is called.
afterEach() : Executes after each of the specs in the
describe
in which it is called.
it() : Defines a single spec.
expect() : Creates an expectation for a spec.
fail() : It marks a spec as failed.
Angular uses Karma test runner which is downloaded and installed by Angular CLI by default. Karma is a test runner for JavaScript based test cases. It can be fine-tuned by editing
karma.conf.js
and src/test.ts
files.
6. Example: Testing HttpClient.post
Find the service class with a method to post data.employee.service.ts
import { Injectable } from '@angular/core'; import { HttpClient, HttpParams, HttpHeaders, HttpErrorResponse } from '@angular/common/http'; import { Observable, of } from 'rxjs'; import { map, catchError, tap } from 'rxjs/operators'; import { Employee } from './employee'; const httpOptions = { headers: new HttpHeaders({ 'Content-Type': 'application/json', 'Authorization': 'my-auth-token' }) }; @Injectable({ providedIn: 'root' }) export class EmployeeService { empUrl = "/api/employees"; constructor(private http: HttpClient) { } addEmployee(emp: Employee): Observable<Employee> { return this.http.post<Employee>(this.empUrl, emp, httpOptions) .pipe( tap(employee => console.log("employee: " + JSON.stringify(employee))), catchError(this.handleError(emp)) ); } private handleError<T>(result = {} as T) { return (error: HttpErrorResponse): Observable<T> => { console.error(error); return of(result); }; } }
export interface Employee { name: string; age: number; }
employee.service.spec.ts
import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing'; import { TestBed } from '@angular/core/testing'; import { HttpClient, HttpResponse } from '@angular/common/http'; import { Employee } from './employee'; import { EmployeeService } from './employee.service'; //Testing of EmployeeService describe('#EmployeeService.addEmploye()', () => { let httpClient: HttpClient; let httpTestingController: HttpTestingController; let empService: EmployeeService; beforeEach(() => { //Configures testing app module TestBed.configureTestingModule({ imports: [HttpClientTestingModule], providers: [ EmployeeService ] }); //Instantiates HttpClient, HttpTestingController and EmployeeService httpClient = TestBed.inject(HttpClient); httpTestingController = TestBed.inject(HttpTestingController); empService = TestBed.inject(EmployeeService); }); afterEach(() => { httpTestingController.verify(); //Verifies that no requests are outstanding. }); //Test case 1 it('should add an employee and return it', () => { const newEmp: Employee = { name: 'Mahesh', age: 25 }; empService.addEmployee(newEmp).subscribe( data => expect(data).toEqual(newEmp, 'should return the employee'), fail ); // addEmploye should have made one request to POST employee const req = httpTestingController.expectOne(empService.empUrl); expect(req.request.method).toEqual('POST'); expect(req.request.body).toEqual(newEmp); // Expect server to return the employee after POST const expectedResponse = new HttpResponse({ status: 201, statusText: 'Created', body: newEmp }); req.event(expectedResponse); }); //Test case 2 it('should turn 404 error into return of the requested employee', () => { const newEmp: Employee = { name: 'Mahesh', age: 25 }; empService.addEmployee(newEmp).subscribe( data => expect(data).toEqual(newEmp, 'should return the employee'), fail ); const req = httpTestingController.expectOne(empService.empUrl); // respond with a 404 and the error message in the body const msg = '404 error'; req.flush(msg, { status: 404, statusText: 'Not Found' }); }); });
7. Run Test Cases
To run the test cases, find the steps.1. Install Angular CLI using link.
2. Download source code using download link given below on this page.
3. Use downloaded src in your Angular CLI application.
4. Run ng test using command prompt. Test result can be seen on command prompt as well as on browser.
5. A chrome for test result will open automatically or we can also use the URL http://localhost:9876/
Find the test result in the browser.

8. References
Angular TestingAngular HttpClient
JASMINE Test