Skip to main content

How to test a http request in Angular application

Testing a http request means that we want to cover a service or a declaration sending it. For that we need to keep the thing as it is and to mock all its dependencies. The last important step is to replace HttpClientModule with HttpClientTestingModule so we can use HttpTestingController for faking requests.

beforeEach(() =>
MockBuilder(TargetService, TargetModule).replace(
HttpClientModule,
HttpClientTestingModule
)
);

Let's pretend that TargetService sends a simple GET request to /data and returns its result. To test it we need to subscribe to the service and to write an expectation of the request.

const service = TestBed.get(TargetService);
let actual: any;

service.fetch().subscribe(value => (actual = value));
const httpMock = TestBed.get(HttpTestingController);

const req = httpMock.expectOne('/data');
expect(req.request.method).toEqual('GET');
req.flush([false, true, false]);
httpMock.verify();

Now we can assert the result the service returns.

expect(actual).toEqual([false, true, false]);

Live example

https://github.com/help-me-mom/ng-mocks/blob/master/examples/TestHttpRequest/test.spec.ts
import { HttpClient, HttpClientModule } from '@angular/common/http';
import {
HttpClientTestingModule,
HttpTestingController,
} from '@angular/common/http/testing';
import { Injectable, NgModule } from '@angular/core';
import { Observable } from 'rxjs';

import { MockBuilder, MockRender, ngMocks } from 'ng-mocks';

// A service that does http requests.
@Injectable()
class TargetService {
public constructor(protected http: HttpClient) {}

public fetch(): Observable<boolean[]> {
return this.http.get<boolean[]>('/data');
}
}

// A module providing the service and http client.
@NgModule({
imports: [HttpClientModule],
providers: [TargetService],
})
class TargetModule {}

describe('TestHttpRequest', () => {
// Because we want to test the service, we pass it as the first
// parameter of MockBuilder. To correctly satisfy its
// initialization, we need to pass its module as the second
// parameter. And, the last but not the least, we need to replace
// HttpClientModule with HttpClientTestingModule.
beforeEach(() => {
return MockBuilder(TargetService, TargetModule).replace(
HttpClientModule,
HttpClientTestingModule,
);
});

it('sends a request', () => {
MockRender();

// Let's extract the service and http controller for testing.
const service = ngMocks.findInstance(TargetService);
const httpMock = ngMocks.findInstance(HttpTestingController);

// A simple subscription to check what the service returns.
let actual: any;
service.fetch().subscribe(value => (actual = value));

// Simulating a request.
const req = httpMock.expectOne('/data');
expect(req.request.method).toEqual('GET');
req.flush([false, true, false]);
httpMock.verify();

// Asserting the result.
expect(actual).toEqual([false, true, false]);
});
});