Search code examples
angularjsangular-resource

Testing $resource services in AngularJS


I am trying to begin writing unit tests for my angular application and hit a stopping block pretty quick as I am unsure of how exactly to mock my service in a testable way.
Is there a way to mock the REST call otherwise it would seem like I need to mirror everything within my service in my tests which doesn't seem right to me, but I am rather new to test writing so maybe this is how it is supposed to be accomplished. Any help would be greatly appreciated.

My service is as follows:

angular.module('resources.users', ['ngResource'])
.factory('User', function($resource) {
   var resource = $resource('/api/index.php/users/:username', {}, {
      'update': {method: 'PUT'}
   });

   resource.getUser = function(username, successCb) {
      return resource.query({username: username}, successCb);
   };

   return resource;
});

My test consists thus far of:

describe('User', function() {
    var mockUserResource;
    beforeEach(module('resources.users'));
    beforeEach(function() {
        mockUserResource = sinon.stub({
            getUser: function(username) {
                mockUserResource.query({username: username});
            },
            query: function() {}
        });
        module(function($provide) {
            $provide.value('User', mockUserResource);
        })
   });
   describe('getUser', function() {
      it('should call getUser with username', inject(function(User) {
          User.getUser('test');
          expect(mockUserResource.query.args[0][0]).toEqual({username: 'test'});
      }));
   })
});

Solution

  • You can mock the requests made by ngResource like this:

    describe('User', function () {
        var mockUserResource, $httpBackend;
        beforeEach(angular.mock.module('myApp'));
    
        beforeEach(function () {
            angular.mock.inject(function ($injector) {
                $httpBackend = $injector.get('$httpBackend');
                mockUserResource = $injector.get('User');
            })
        });
    
        describe('getUser', function () {
            it('should call getUser with username', inject(function (User) {
                $httpBackend.expectGET('/api/index.php/users/test')
                    .respond([{
                    username: 'test'
                }]);
    
                var result = mockUserResource.getUser('test');
    
                $httpBackend.flush();
    
                expect(result[0].username).toEqual('test');
            }));
    
        });
    });
    

    Demo