When Angular has finally come out, it was possible to test HTTP requests, but it was a tedious work to set it up properly. Multiple dependencies were needed during the module setup and the faked connections were only available through an Observable object. To make things even harder, no built-in assertions were available for the requests. The Angular team knew these problems, so with Angular 4.3 they introduced a new module called HttpClientModule that intends to replace the existing HttpModule and make usage and testing easier by providing straightforward interfaces.
In this tutorial I’ll show write tests with the new HttpClientModule.
First we will test a basic request, the GET request. It will call an url without a body or additional headers. The Github API has an endpoint for retrieving public profile information about users. The profile information is returned in JSON format.
The getProfile method sends a GET request to the API and returns the response. Every request made with the HttpClientModule returns an Observable. The returned value is the parsed JSON response body.
The first thing we have to do is to set up the test dependencies. The HttpClient dependency is required. If we don't provide it, we will get this error message: No provider for HttpClient!.
Angular provides the HttpClientTestingModule that resolves every dependency needed for HTTP testing. There is no more tedious setup: you don’t need MockBackend and BaseRequestOptions as dependencies and the factory method for Http won’t be necessary, either. Below you can see what the previous setup looked like. Multiple lines collapsed to just one module.
Let’s use the new setup to write the first test that checks the result of the request.
We can control the backend with the HttpTestingController. After we get the instance of it from the TestBed, we can set expectations against the incoming requests. In this example only one request is expected with an exact url. To set response we just need to call flush, which converts the given object to JSON format by default. At last we need to check the response through the subscribe method.
GET requests are good for retrieving data, but we’ll make use of other HTTP verbs to send data. One example is POST. User authentication is a perfect fit for POST requests. When modifying data stored on the server we need to restrict access to it. This is usually done with a POST request on the login page.
Auth0 provides a good solution for handling user authentication. It has a feature to authenticate users based on username and password. To demonstrate how to test POST requests, we will send a request to the Auth0 API. We won’t be using their recommended package here, because it would abstract out the actual request, but for real-world scenarios I would recommend using it.
The main difference between this example and the previous one is that here we are sending a JSON payload to the server and appending additional headers onto it. We don’t have to manually JSON.stringify the payload --- the request methods will take care of it. The response will be in text format, no conversion will be done.
Let’s look at the test to see how we can check every detail of the request.
The expectOne method can take different arguments. The first one we used at the profile request was a simple string. It only checked the url being called. When we pass an object to this method, we can check the requests method also, but nothing else. To make more precise assertions, we have to pass a function to the expectOne method.
The function gets the request as an argument. You have to return a boolean value: true if every detail matches your expectation and false otherwise. This way you can check every aspect of a request.
We managed to set up tests from a basic GET request to a more complex POST request. We have seen that services with the new HTTP module can be much cleaner compared to the old one. It is always a good idea to keep an eye on the new features of Angular.
To see the tests in action check out this GitHub repository.