在下面的 SampleController 中,如何对 postAttributes 函数调用 sampleService.updateMethod 即可。我遇到了麻烦,因为updateMethod返回了promise。
angular.module('sampleModule')
.controller('SampleController', SampleController);
SampleController.$inject =['sampleService'];
function SampleController(sampleService){
this.postAttributes = function() {
sampleService.updateMethod(number,attributes)
.then(function(response){
//do something on successful update
},function(response){
//do something on unsuccessful update
});
};
}
这是我的工厂服务:
angular.module('sampleModule')
.factory('sampleService', sampleService);
sampleService.$inject = ['$http'];
function sampleService($http) {
return {
getMethod: function(acctNumber){
return $http({
method: 'GET',
url: //api endpoint
});
},
updateMethod: function(number, attributes){
return $http({
method: 'PUT',
url: //api endpoint,
data: //payload
});
}
};
}
我想在控制器规范中模拟工厂服务,而不是直接将实际服务注入$ controller,因为大多数单元测试指南都指定在隔离下测试一个单元。
样本控制器规范:
describe('SampleController Test', function(){
var $controller;
var service;
beforeEach(angular.mock.module('sampleModule'));
beforeEach(angular.mock.inject(function(_$controller_){
$controller = _$controller_;
}));
it('Testing $scope variable', function(){
var sampleController = $controller('SampleController', {
sampleService: service, //mocked factory service
});
sampleController.postAttributes(); //calling the function first
//here I would like to make an assertion to check if
//sampleService.updateMethod has been called with certain parameters
//how do I do that??
});
});
答案 0 :(得分:3)
用Google搜索并找到一个模拟工厂服务的解决方案,并遵循@TehBeardedOne等承诺创建方法,并让它从模拟服务中返回。
describe('SampleController', function(){
var mockService, controller, deferred, $rootScope;
beforeEach(function(){
angular.mock.module('sampleModule');
angular.mock.module(function($provide){
$provide.factory('sampleService', function($q){
function updateMethod(acct, attr){
deferred = $q.defer();
return deferred.promise;
}
return{updateMethod: updateMethod};
});
});
angular.mock.inject(function($controller, sampleService, _$rootScope_){
$rootScope = _$rootScope_;
mockService = sampleService;
spyOn(mockService, 'updateMethod').and.callThrough();
controller =$controller('SampleController', {
sampleService: mockService,
})
});
});
it('postAttributes function should call updateMethod', function(){
controller.postAttributes();
expect(mockService.updateMethod).toHaveBeenCalled();
expect(mockService.updateMethod).toHaveBeenCalledWith(controller.accountNumber, controller.attributes);
});
it('postAttributes success block', function(){
controller.postAttributes();
var res = {
data: '2323'
}
deferred.resolve(res);
$rootScope.$digest();
expect(//something in success block).toBe(something);
});
it('postAttributes failure block', function(){
controller.postAttributes();
var res = {
data: '9898'
}
deferred.reject(res);
$rootScope.$digest();
expect(controller.lame).toBe('dont type shit');
});
});
我使用 $ provider 服务嘲笑 sampleService ,并使 updateMethod < / strong>使用 $ q 返回承诺。稍后,您可以解决或拒绝承诺,并测试其阻止的成功和失败块。
答案 1 :(得分:1)
您需要使用间谍来检查是否正在调用该函数。有几种方法可以做到这一点,因为我确定你可能已经注意到了。您还需要注入$q
和$rootScope
,因为您需要循环摘要周期以返回承诺。
事实上,如果你想要做的就是检查是否正在调用该函数,那么简单的间谍就可以了。你甚至不必退还诺言。话虽这么说,如果你想继续通过postAttributes()
函数并测试这个函数中的其他东西,那么你需要返回承诺来做到这一点。这是适合我的方法。这样的事情应该有效。
describe('SampleController Test', function(){
var $controller;
var service;
var $q;
var $rootScope;
var updateMethodDeferred;
var ctrl;
var mockHttpObject;
beforeEach(angular.mock.module('sampleModule'));
beforeEach(angular.mock.inject(function(_sampleService_, _$q_, _$rootScope_, _$controller_){
service = _sampleService_;
$q = _$q_;
$rootScope = _$rootScope_;
$controller = _$controller_;
mockHttpObject = {
//add mock properties here
}
updateMethodDeferred = $q.defer();
spyOn(service, 'updateMethod').and.returnValue(updateMethodDeferred.promise);
ctrl = $controller('SampleController', {
sampleService: service, //mocked factory service
});
}));
it('Testing $scope variable', function(){
ctrl.postAttributes();
expect(service.updateMethod).toHaveBeenCalled();
});
it('Should do something after promise is returned', function(){
ctrl.postAttributes();
updateMethodDeferred.resolve(mockHttpObject);
$rootScope.$digest();
expect(/*something that happened on successful update*/).toBe(/*blah*/)
});
});