背景:
我正在为angular js控制器编写单元测试,它使用包含在服务中的角度$资源(用于可维护性目的).
我正在为angular js控制器编写单元测试,它使用包含在服务中的角度$资源(用于可维护性目的).
示例控制器:
name = 'app.controllers.UsersIndexCtrl' angular.module(name,[]) .controller(name,[ '$scope' '$location' '$dialog' 'Users' 'UserRoles' ($scope,$location,$dialog,Users,UserRoles) -> # Get users list $scope.users = Users.query() # rest... ])
示例资源服务:
angular.module('app.services.Users',[]) .factory 'Users',['$rootScope','$http','$resource','$location',($rootScope,$http,$resource,$location)-> baseUrl = '/users' Users = $resource baseUrl + '/:userId',{userId: '@_id'} Users.getStatus = -> console.log 'User::getStatus()' req = $http.get baseUrl + '/status' req.success (res)-> $rootScope.globalUserAccountSettings = res unless $rootScope.$$phase then $rootScope.$apply() # other,custom methods go here... ])
大多数单元测试示例使用$httpBackend进行角度建议,从而模拟控制器中的$http服务.说实话,我怀疑这是否是一个好习惯,因为如果这样做我必须在所有控制器测试中硬编码请求路径,我想隔离单元行为. $httpBackend mock非常棒,但前提是你直接在控制器中使用$resource.
使用$httpBackend的典型单个测试看起来像:
it 'should be able to add a new empty user profile',-> $httpBackend.flush() l = $scope.users.length $httpBackend.expect('POST','/users').respond _.cloneDeep mockResponSEOK[0] $scope.add() $httpBackend.flush() expect($scope.users.length).toEqual l + 1
如果我创建了一个模拟User资源类实例,例如:
angular.module('app.services.Users',-> class Users $save:(cb)-> $remove:-> @query:-> @get:->
Angular DI机制将以透明的方式覆盖旧的“app.services.Users”模块,并使我能够使用茉莉花间谍运行检查.
困扰我的是我无法找到支持我的想法的单一例子.所以问题是,你会使用哪一个,为什么或我做错了什么?
解决方法
我认为如你所建议的那样,使用Jasmine间谍将其存储在服务级别更有意义.此时您正在对控制器进行单元测试,而不是服务 – 确定http请求的确切方式不应该是此测试的关注点.
您可以在您的规范中执行以下操作:
var Users = jasmine.createSpyObj('UseRSStub',['query','get']); beforeEach(inject(function($provide) { $provide.factory('Users',function(){ return Users; }); });