TDD in Angular - Basics of HTTP Testing
Tags: angular, javascript, tdd
Published: 2020-10-01 00:14:19

It won't be much of a Web Application if it doesn't make HTTP requests, does it? However, it's easy to forget that these need to be tested as well! 

In this article, I'll cover how to unit test HTTP requests in your Angular Application so you can have the confidence that they'll always work as expected.

_Code for the article can be found [here](https://github.com/Qarun-Qadir-Bissoondial/ng-jasmine-testing-demo/tree/testing-http)._

## Setting up our code

Let's say that our HTTP calls live in a service that handles to-do items. We can do our basic CRUD operations: getting our to-do items or a single one, creating new items, updating or deleting items.

I'll be using [JSONPlaceHolder](https://jsonplaceholder.typicode.com/) for this since it's the quickest way to get started. The most barebones CRUD service should look like this: 

{% gist https://gist.github.com/Qarun-Qadir-Bissoondial/7634fcb13ad6441131b0485d8f8eb27e %}
 
After importing `HttpClientTestingModule`, the auto-generated spec file should look like this:

{% gist https://gist.github.com/Qarun-Qadir-Bissoondial/98f96d99b42d235fb0401cf42db3a21f %}

At this point your only test ("it should be created") should be passing.

## HTTP Testing Method

Remember that during testing, _we're not actually making any requests_. We're only concerned with if the request was sent and if a response is handled properly when it returns. Anything that happens in between that is out of the scope of unit testing. 

Therefore, let's say that we're unit testing a GET request, we only care that the request is sent and, if the request is successful, some data comes back.

_Keep in mind that Angular HttpClient uses Observables rather than promises so we have to adjust our tests accordingly!_

Angular provides an entire module to help us test HTTP Requests called the `HttpClientTestingModule` that allows us to:

 - Mock a request
 - Create a fake request with any status code
 - Pass along a response with fake data
 - Cancel a request
 - And much much more!

This means we can test our requests from every angle possible and have our application handle as much cases as possible. I'll cover these in future articles. Let's get set up!

## Setting up HTTP Mocks

We need to establish a Mock network that allows us to control when requests are sent, what data is returned and whether or not the request was successful. This comes in the form of `HttpTestingController` as seen below:

{% gist https://gist.github.com/Qarun-Qadir-Bissoondial/a740ac9e7fe287fd7c10785d65414d2e %}

Notice that in the `afterEach` block, we called `httpMock.verify()`. This ensures that there are no pending requests in our mock network before moving on to other tests.

Now we can really start testing our code!

## Testing Requests

We want to test `getSingleTodo`. Based on the function name, we can expect that the HTTP response will contain a todo object. Let's represent our expectations as tests.

{% gist https://gist.github.com/Qarun-Qadir-Bissoondial/d3a8a4493399646271f89614273bbeb3 %}

In the above code, we: 

 - ran our `getSingleTodo` function and expected the result to be defined
 - used the controller to expect a request to have the URL `https://jsonplaceholder.typicode.com/todos/1`
 - expected the request to be a GET request
 - used the controller to manually send the request with the fake todo data.

Under normal circumstances, the `getSingleTodo` function would have made an actual request but our `HttpTestingController` intercepted the request and returned the fake data using `testRequest.flush`.

We can now use this information to test POST requests. These contain a request body and can return data along with the status code.

{% gist https://gist.github.com/Qarun-Qadir-Bissoondial/93bcc8c7657eb32f0b0df91c2e34a877 %}

This test ensures a POST request is sent to the correct URL and the created data is returned.

## Conclusion

In this article, we learned: 
 - the theory behind testing HTTP requests by using a mock network
 - setting up the mock network using `HttpTestingController`
 - running fake requests and testing their URLs, methods and return values 

The next article will show how to control fake requests so we can test our application in the event of unauthorized requests, server crashes and basic error handling.

Hope you enjoyed reading! :smile: