Testing $resource services in AngularJS Testing $resource services in AngularJS angularjs angularjs

Testing $resource services in AngularJS


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


zsong's answer greatly helped me understand this, but I would like to expand on how it works. In case it gets edited, I list the code again here:

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');        }));    });});

What's going on here?

1

beforeEach(angular.mock.module('myApp'));

We tell the Angular injector ($injector and angular.mock.inject) to inject things defined in the myApp module. You can think of it as defining a module dependency without a dependent module. Compare with how things defined in the myApp module can be injected in, say, a controller in a angular.module('myOtherApp', ['myApp']) module.

2

beforeEach(function () {    angular.mock.inject(function ($injector) {        $httpBackend = $injector.get('$httpBackend');        mockUserResource = $injector.get('User');    })});

Before each spec, run the function ($injector) function with dependencies injected. In this case, the dependency ($injector) is resolved implicitly from the parameter name. A functionally equivalent variant of this snippet is

beforeEach(function () {    angular.mock.inject(['$httpBackend', 'User', function ($httpB, User) {        $httpBackend = $httpB;        mockUserResource = User;    }]);});

Here we have instead declared the dependencies explicitly, and are free to use any parameter names we wish.

3

it('should call getUser with username', inject(function (User) {

Again, the test function is injected with the implicitly resolved User service as a parameter, though it isn't actually used.

Notice that this time there is no wrapper function around the inject call. inject invokes the passed function immediately if a spec is currently running, but otherwise it returns a wrapper function (see the inject docs and source code), so we don't actually need the wrapper function. Thus, we could have written the beforeEach snippet above like this:

beforeEach(angular.mock.inject(function ($injector) {    $httpBackend = $injector.get('$httpBackend');    mockUserResource = $injector.get('User');}));