我正在为控制器编写测试。一种方法调用服务中的方法,该方法使用promise。在我的测试中,我嘲笑了服务,并且(我认为)正确地嘲笑了这个承诺。我一直在关注此博客文章:http://codingsmackdown.tv/blog/2012/12/28/mocking-promises-in-unit-tests/。
这是测试代码:
describe('Controller: ResultsController', function () {
'use strict';
var ctrl;
var ResultsServiceMock;
var RouteServiceMock;
var $scope;
var mockResults;
var mockPromise;
var q;
var deferred;
beforeEach(module('waApp'));
beforeEach(function() {
ResultsServiceMock = {
get: function(query) {
deferred = q.defer();
return deferred.promise;
}
};
RouteServiceMock = {
getParams: function() {
}
};
});
beforeEach(inject(function(
$rootScope,
$controller,
$q
) {
$scope = $rootScope.$new();
q = $q;
ctrl = $controller('ResultsController', {
$scope: $scope,
results: ResultsServiceMock,
route: RouteServiceMock
});
}));
it('Should simulate requesting results from the api', function() {
spyOn(ResultsServiceMock, 'get').andCallThrough();
spyOn(RouteServiceMock, 'getParams').andReturn({input:'hamburger'});
$scope.getResults({input:'hamburger'}); // TODO give params. try query()
deferred.resolve();
$scope.$root.$digest();
expect($scope.getResults).toHaveBeenCalled();
});
});
但是,当我运行测试时,我收到以下错误:
Chrome 35.0 (Mac) Controller: ResultsController Should simulate requesting results from the api FAILED
TypeError: Cannot read property 'resolve' of undefined
at null.<anonymous> (/Users/maryc/wa/app/results/results-controller_test.js:70:17)
Chrome 35.0 (Mac): Executed 14 of 14 (1 FAILED) (0.313 secs / 0.093 secs)
我不明白这个错误来自哪里;是因为对ResultsServiceMock的间谍调用不起作用?任何帮助将不胜感激。
函数getResults如下:
$scope.getResults = function(params) {¬
$scope.$emit('startGetResults');¬
$scope.loading = true;¬
$scope.podRequestStatus.init = false;¬
$scope.podRequestStatus = {¬
async: {}¬
};¬
var didyoumeans;¬
if(params.didyoumeans) {¬
didyoumeans = params.didyoumeans;¬
delete params.didyoumeans;¬
}¬
ResultsService.get(params).success(function(result) {¬
$scope.$emit('getResultsSuccess');¬
if(!_.isUndefined(didyoumeans)) {¬
$scope.results.queryresult.didyoumeans = didyoumeans;¬
} else if(!_.isUndefined(result.queryresult.didyoumeans)) {¬
if (!_.isArray(result.queryresult.didyoumeans)){¬
result.queryresult.didyoumeans = [result.queryresult.didyoumeans];¬
}¬
$scope.getResults({input: result.queryresult.didyoumeans[0].val, didyoumeans: result.queryresul t.didyoumeans});¬
return;¬
}¬
$scope.loading = false;¬
$scope.podRequestStatus.init = true;¬
if(result.queryresult.success === false) { //TODO is this result.results.queryresult.success??¬
if(result.queryresult.error !== false) {¬
$log.error('Results error', 'code: ' + result.queryresult.error.code, 'msg: ' + result.quer yresult.error.msg);¬
switch (result.queryresult.error.code){¬
case '3000':¬
$location.url('/blockedip');¬
break;¬
}¬
return;¬
}¬
if($scope.results.queryresult.examplepage && $scope.results.queryresult.examplepage.category) { ¬
$scope.examples();¬
}¬
// convert tips to an array if we have a single item¬
if($scope.results.queryresult.tips && !_.isArray($scope.results.queryresult.tips)){¬
$scope.results.queryresult.tips = [$scope.results.queryresult.tips];¬
}¬
$log.error('Results error');¬
return;¬
}¬
$scope.results.queryresult.pods = _.map($scope.results.queryresult.pods, function(pod) {¬
pod.priority = PodService.priority.initial;¬
return pod;¬
});¬
if ($scope.results.queryresult.sources && _.where($scope.results.queryresult.sources, {'text':'Fina ncial data'})) {¬
$scope.$emit('financialData', true);¬
} else {¬
$scope.$emit('financialData', false);¬
}¬ ¬
$scope.asyncPods(PodService.priority.async, 'async');¬
$scope.recalculate();¬
$scope.related();¬
}).error(function() {¬
$log.error('error occurred during ResultsService.get call in ResultsController');¬
});¬
};¬
函数asyncPods,recalculate和related是ResultsController中的其他三个方法。
编辑:修复了第一个错误后,我现在在运行测试时遇到以下错误:
Chrome 35.0 (Mac) Controller: ResultsController Should simulate requesting results from the api FAILED
TypeError: undefined is not a function
at Scope.$scope.getResults (/Users/maryc/wa/.tmp_test/results-controller.js:222:36)
at null.<anonymous> (/Users/maryc/wa/app/results/results-controller_test.js:67:16)
此错误来自getResults()开头的行,该行调用ResultsService.get()。这似乎暗示我的承诺要么没有得到解决,要么调用$ scope.getResults()以某种方式失败?
ResultsService的.get()函数的代码是:
get: function(query) {¬
this.reset();¬
return ApiService.get({¬
params: UtilService.merge(query, {¬
async: true,¬
scantimeout: 1,¬
formattimeout: 8,¬
parsetimeout: 5,¬
format: 'image,plaintext,imagemap',¬
banners: 'true'¬
}),¬
timeout: abort.promise,¬
type: 'init',¬
cache: UserService.user.cacheResults¬
}).success(function(data){results.queryresult = data.queryresult;});¬
},¬
我现在想知道问题是否.get本身包含一个承诺?
答案 0 :(得分:0)
根据您目前所包含的信息,我猜测可能导致问题的原因。
在$scope.getResults()
方法中,您调用了get()
的{{1}}方法,因此该服务的名称似乎是ResultsService
。
但在单元测试中,您将ResultsService
作为ResultsServiceMock
传递:
results
它应该是ctrl = $controller('ResultsController', {
$scope: $scope,
results: ResultsServiceMock,
route: RouteServiceMock
});
而不是这样:
ResultsService
在此更改之后,您可能会遇到其他问题,但它应该会传递错误:
ctrl = $controller('ResultsController', {
$scope: $scope,
ResultsService: ResultsServiceMock,
RouteService: RouteServiceMock
});
希望这有帮助。