在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注入器( $injector
和angular.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'); }));