For better testability, and other important reasons, it's generally advisable to add some form of abstraction around your http access layer. However, Angular offers its own “hook” for mocking if your code under test has a direct dependency on the $http service. In this post I will show how to tap into Angular's httpBackend service to define mocked responses to http requests.

For better testability, and other important reasons, it's generally advisable to add some form of abstraction around your http access layer. However, Angular offers its own “hook” for mocking if your code under test has a direct dependency on the $http service. In this post I will show how to tap into Angular's httpBackend service to define mocked responses to http requests.

In the code below I have defined a simple greeting controller for retrieving greetings from the server through an ajax call.

angular.module('app').controller('greetingController',[
        '$http',
        '$scope',
        function($http,$scope){
            $http.get('http:/localhost:3000/getGreeting').then(function(result){
                $scope.greetings = result.data;
            });
}]);

At first glance this code looks challenging to test due to the tight coupling between the controller and the ajax call. However, it turns out that Angular can help us out here through its own abstraction layer in the $http service.

The solution is to use the built in $httpBackend service to define a mock response. Below is a simple demonstration of how this can be done.

describe('greetingTest', function(){
    var greetings = [{message:'hello friend'}];
    var $controller;
    var $scope;
    var $httpBackend;
    var $q;
    beforeEach(function() {

        module('app');

        inject(function ($injector) {
            $scope = $injector.get('$rootScope').$new();
            $controller = $injector.get('$controller');
            $httpBackend = $injector.get('$httpBackend');
            $q = $injector.get('$q');
        });

    });
    it('should load mocked greetings', function(){

        $httpBackend.whenGET('http:/localhost:3000/getGreeting').respond(200, greetings);
        $controller('greetingController',{'$scope':$scope});
        $httpBackend.flush(); //needed to resolve and handle promise returned by $http

        expect($scope.greetings).toEqual(greetings);
    });
});

After injecting the necessary dependencies, all you have to do is call $httpBackend.whenGET to define the response.