How to test an HTTP request in Angular
Testing an HTTP request means covering a service or declaration that sends it.
For that, we need to keep the service or declaration as it is and mock all its dependencies.
The last important step is to replace HttpClientModule with HttpClientTestingModule
so we can use HttpTestingController to fake 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 write an expectation for 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/main/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(() =>
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]);
});
});