【发布时间】:2014-04-10 11:29:44
【问题描述】:
我们最近开始在我们的控制器中加入 Promise 以同时处理多个请求,并且它在应用程序中工作,但事实证明,对这些进行单元测试非常困难,我很难准确掌握它的含义是我失踪了。以下是我要测试的两个非常简化的 sn-ps。
控制器:
angular.module('testengine').controller('testController', [
'$scope',
'$q',
'Api',
function($scope, $q, Api) {
$scope.getTest = function (deferred) {
// do stuff...
Api.test.get(params, function(response) {
// do stuff with response
if (deferred) {
deferred.resolve(); // if success
}
});
};
$scope.runTest = function () {
// do stuff...
var promises = [];
var deferred = $q.defer();
promises.push(deferred.promise);
$scope.getTest(deferred);
$q.all(promises).then(function () {
$scope.navigate();
}, function () {
// do stuff with rejected
});
};
$scope.navigate = function () {
// do stuff
};
}]);
测试:
describe('Controller:', function () {
var root, scope, controllerFactory, $q;
function createController () {
return controllerFactory('testController', {
$scope: scope
});
}
beforeEach(function () {
module('testengine');
});
beforeEach(inject(function ($rootScope, $controller, _$q_) {
root = $rootScope;
scope = $rootScope.new();
controllerFactory = $controller;
$q = _$q_;
});
it('should run test', function () {
createController();
var deferred = $q.defer();
spyOn(scope, 'getTest').andReturn(deferred.resolve());
spyOn(scope, 'navigate');
$scope.runTest();
root.$apply();
expect(scope.navigate).toHaveBeenCalled();
});
});
根据我在 Promise 和 $q 上阅读的所有示例和文档,这应该有效,但它没有,相反我得到:
Expected spy navigate to have been called but it was never called.
我猜是因为它不是我在模拟间谍中解析的同一个延迟对象,但我应该如何模拟它?我是否必须在控制器或范围上绑定延迟对象或什么?
您看到的结构的原因是因为使用 getTest() 的方法不同(有些不仅使用该请求,还使用其他方法,因此承诺)。此外,getTest() 在另一个测试中单独测试,这就是为什么我要模拟该函数以及其中发出的任何请求。
感谢任何帮助,如果我犯了一些明显的错误,我很乐意教育自己对 Angular 还是很陌生。
【问题讨论】:
-
我怀疑重构可以做一些事情:看起来有点像
Api.test.get应该返回一个承诺,而不是接受一个回调。$scope.getTest也应该返回一个承诺,而不是影响它然后解析的延迟对象。我认为这会使事情变得更加标准,并使他们的测试也最标准和(希望)更简单。诚然很难知道/确定,因为我不确定这些功能都做了什么。阅读链式 Promise 可能会有所帮助(尽管 Angular 文档对此非常简单!)。
标签: javascript angularjs unit-testing jasmine