How to unit test Angular’s $resource and $http

Unit testing of Angular’s underlying $http can be very tricky. I’ve some spent considerable time to get the unit testing up and running. What was running OK in a live application, was not working at all in a unit test. I was getting error message “No pending request to flush !” all the time.

unit

My controller looked something like this

//TypeScript

Module.controller("UsersCtrl", [<any>
        "$scope",
        "$location",
        "User",
        function (
            $scope,
            $location : ng.ILocationService,
            User: ng.resource.IResourceClass) {

            $scope.findUsers = () => {
               User.query({ email: $scope.searchTerm, showAdHoc: $scope.showAdHoc }, 
                function (data: any) {
                    //data arrived. Do something with them
                }, function (errorData: any) {
                    //server error. Notify user
                });
            };
}]);
}

And the unit test looked like this

it('should set matchedUsers.isLoading when searching', inject(function ($controller) {
            $httpBackend.when('GET', '/api/user?email=a&showAdHoc=false').respond({});

            controller = $controller('UsersCtrl', { $scope: scope });
            scope.matchedUsers.isLoading = false;
            scope.searchTerm = 'a';

            //Method being tested
            scope.findUsers();

            expect(scope.matchedUsers.isLoading).toBe(true);
            //this fails on "No pending request to flush !"
            $httpBackend.flush();
        }));

This did not work and I just could not understand why. According to example on Angular’s doc site  everything seemed fine. The problem was hidden in the underlying $http service, see documentation here.

You have to explicitly call $scope.$apply() which triggers the $digest() which takes care of the $http request.

So the working unit test code should look like this:

scope.$apply(function() {
 scope.findUsers();
});

//now it works
$httpBackend.flush();