在AngularJS中testing$资源服务

我正在尝试为我的angular度应用程序开始编写unit testing,并且非常快地触发了一个停止块,因为我不确定如何以可testing的方式模拟我的服务。
有没有一种方法来嘲弄REST的呼叫,否则似乎我需要在我的服务内反映我的服务中的一切似乎并不正确,但我是新的testing写作,所以也许这就是它应该如何要完成。 任何帮助将不胜感激。

我的服务如下:

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

我的testing到目前为止:

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

你可以像这样嘲笑ngResource所做的请求:

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

演示

zsong的回答很大程度上帮助我理解了这一点,但是我想扩展它的工作原理。 如果它被编辑,我在这里再次列出代码:

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

这里发生了什么?

1

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

我们告诉Angular注入器( $injectorangular.mock.inject )注入myApp模块中定义的东西。 你可以把它看作定义一个没有依赖模块的模块依赖。 比较myApp模块中定义的东西如何在angular.module('myOtherApp', ['myApp'])模块中注入一个控制器。

2

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

在每个规范之前,运行注入依赖关系的function ($injector)函数。 在这种情况下,依赖关系( $injector )将从参数名称中隐式parsing。 这个片段的function等同的变体是

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

在这里,我们已经明确声明了依赖关系,并且可以自由使用我们希望的任何参数名称。

3

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

同样,testing函数注入隐式parsing的User服务作为参数,尽pipe它没有被实际使用。

注意这次inject调用没有包装函数。 如果一个spec正在运行, inject立即调用传递的函数,否则它会返回一个包装函数(请参阅注入文档和源代码 ),所以我们实际上并不需要包装函数。 因此,我们可以这样写上面的beforeEach片段:

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