Reputation: 165
Hey everyone, I'm adding some Karma-Jasmine unit-testing to my Angular 2 project and I cannot for the life of me get the coverage to hit the RXJS operators in my service methods.
The tests are using the HttpClientTestingModule and HttpTestingController.
Here's a simple example just using the map operator.
MyService:
getAssetCount(): Observable<AssetModel[]> {
return this.http
.get('/myproject/v1/asset-count')
.pipe(map(response => response as AssetModel[]));
}
MyService.spec:
service = testBed.get(MyService);
httpMock = testBed.get(HttpTestingController);
...
it('should getAssetCount', () => {
const dummyResponse = [{...}];
service.getAssetCount().subscribe((response: AssetModel[]) => {
expect(response).toEqual(dummyResponse);
const req = httpMock.expectOne(
'/myproject/v1/asset-count'
);
expect(req.request.method).toBe('GET');
req.flush(dummyResponse);
httpMock.verify();
});
});
The resulting coverage:
I would have thought having a subscription to the observable in the test would trigger the map() call, but perhaps I'm misunderstanding how these mock services work.
From looking around, it seems like switching to the XHRBackend instead of the HttpClientTestingModule to generate dummy 200/404/etc responses could solve the issue, but besides being more boilerplate, it seems like most people were suggesting to use the TestingModule instead.
Upvotes: 6
Views: 1647
Reputation: 6060
Try moving the flush()
and other testing logic outside of the subscribe, just leaving the expect(response) inside. Something like this:
it('should getAssetCount', () => {
const dummyResponse = [{...}];
service.getAssetCount().subscribe((response: AssetModel[]) => {
expect(response).toEqual(dummyResponse);
});
const req = httpMock.expectOne(
'/myproject/v1/asset-count'
);
expect(req.request.method).toBe('GET');
req.flush(dummyResponse);
httpMock.verify();
});
Upvotes: 5