Reputation: 689
I am using Angular 9+.
While unit testing
services that implement httpClient
and make http requests, I referred this documentation by Angular Team. I followed the process and got success in the unit tests also.
Following is the code (taken from the doc):
it('can test HttpClient.get', () => {
const testData: Data = {name: 'Test Data'};
// Make an HTTP GET request
httpClient.get<Data>(testUrl)
.subscribe(data =>
// When observable resolves, result should match test data
expect(data).toEqual(testData)
);
// The following `expectOne()` will match the request's URL.
// If no requests or multiple requests matched that URL
// `expectOne()` would throw.
const req = httpTestingController.expectOne('/data');
// Assert that the request is a GET.
expect(req.request.method).toEqual('GET');
// Respond with mock data, causing Observable to resolve.
// Subscribe callback asserts that correct data was returned.
req.flush(testData);
// Finally, assert that there are no outstanding requests.
httpTestingController.verify();
});
My question is:
Since http calls
are asynchronous
, why is not fakeAsync() written in any of the tests provided in the docs? Like normally when unit testing asynchronous methods
( setTimeout() , setInterval()
), the docs provided in angular shows that we need a fake zone.js which appends all the async requests to an array and then we use flushMicrotasks() or tick() to further facilitate the calls.
How is the control flow happening when req.flush()
is called? We have made a call to the function httpClient.get<Data>(testUrl)
which subscribes to the observable and and flush is used to just resolve it. So the entire flow in the test spec is happening async / sync?
Upvotes: 0
Views: 2871
Reputation: 12206
the nature of rxjs allows you to handle streams without thinking wether they are synchronious or asynchronious. for testing http client things are made synchroniuous for ease of testing. httpClient is made in a way that async code is behaving sync in tests, because every "async" work is based on rxjs streams. streams api is strong enough to make async logic - sync in some cases. by async in js world it is usually ment that before execution of this code, js execution callstack should become empty
req.flush(...);
will invoke subscribe handler inside of your component just in this line. just after it you can assert the result of that handler
Upvotes: 1