Unit Testing a Service that Makes an API Call Using $httpbackend

Friday, August 22, 2014

Introduction

This is part of a series on Unit Testing in AngularJS. You can see my others posts:

Creating a Single Page Application will inevitably require making an API call to a service at some point, and AngularJs provides two mechanisms to do accomplish this in its framework. The one instance is using the ngResource module, and the other approach is using the $http service. Personally, I am sort of torn as to what approach to use but I am finding my self gravitating more towards using the $http service just because it is more customizable. I think ngResource shines if you have a predictable set of RESTFUL API calls and you just want to make calls and get responses back, but if you want so more control of things like exception management, or provide a chain of promises, I find the $http service to be more straight forward in setting up.

$httpBackend

Another nice thing the $http service is that is comes with the corresponding $httpBackend service which can be used for mocking calls so your unit test have no external dependencies. After all, that is whole point of a unit test is that it is self contained and not reliant on any outside factors.


The Service

So in this example I have a service that makes an API call to get the friends for a current user:

 

This service has a GET call and a POST call and I want to write a test that will test a mock of the POST call.


The Test Setup

So lets look at the unit test and talk about what is going in this code.

So the first thing that is done is that we need to define our service and also define the $httpBackend service that will be mocking our calls.

I am also defining a mocked response that will be returned one the service is called.

In the beforeEach section, the service and $httpBackend are injected into our environment before each test.

And then after each call we want to ensure that the calls were expected to be made were actually made and that there were no exceptions thrown on those calls.

The Unit Test

Here is the first line of code from the test

$httpBackend.expectPOST('/api/friends/refresh').respond(refreshResponse);

 

This tells the $httpBackend service to expect a POST call to be made to a service and that it will return the refreshResponse object that was defined at the top of the page.

The next lines of code are the actual execution of the service.

var deferredResponse =  friendsApiService.refreshUsers();

var users;

deferredResponse.then(function(response){

    users = response.data;

});

Since we want to preserve the asynchronous nature of the call while at the same time be able to test the response of the call we will then need to flush the response. This will explicitly flush any pending request so that when we can evaluate the response it returns within the unit test. If we did not do this, since our call is asynchronous, our test would finish before the call was actually completed.

Once the flush is complete, we now can evaluate our response to see of our test is working.

 

 

comments powered by Disqus