【发布时间】:2016-12-18 14:37:25
【问题描述】:
我花了很多时间尝试对在控制器中生成/跟踪承诺的指令进行单元测试,可以在此处查看如何完成此操作的示例:https://plnkr.co/edit/d8wMq0qlpiE4P25q5lhB
指令:
.directive('testDirective', function() {
return {
scope: {
save: '&',
},
template: '<div><a href="#" ng-click="handleSave($event)">Click Here</a></div>',
link: function(scope, element, attr, controllers) {
scope.someData = {
saving: false
};
scope.handleSave = function() {
scope.someData.name = parseInt(Math.random() * 100);
scope.someData.saving = true;
scope.someData.error = false;
scope.someData.id = null;
return scope.save()(scope.someData)
.then(function(data) {
scope.someData = data;
})
.catch(function(err) {
scope.someData.error = true;
})
.finally(function() {
scope.someData.saving = false;
});
};
}
};
})
控制器:
.controller('TestCtrl', function($scope, $q, $timeout) {
$scope.saveCtrl = function(directiveData) {
return $q(function(resolve, reject) {
$timeout(function() {
if (Math.round(Math.random())) {
directiveData.id = parseInt(Math.random() * 100);
resolve(directiveData);
} else {
reject(new Error());
}
}, 2000)
});
}
});
模板:
<test-directive save="saveCtrl"></test-directive>
它可以作为示例中的组件使用,但测试无法完成,因为 .finally() 永远不会被调用。我尝试了很多变体来强制使用 $digest,但似乎没有任何东西可以完成承诺。
【问题讨论】:
-
我是一个角度n00b,有没有办法将指令注入测试并直接调用
link方法,或者您是否必须编译和消化它才能对其进行评估? -
对于最低限度可行的测试,是否可以从
saveCtrl中删除 $timeout,以便立即解决承诺?并通过不使用随机来消除测试中的不确定性?理想情况下,可以有 2 个单独的测试一个reject分支和一个resolve分支? -
@dm03514 当然,我将它添加到实际指令的功能中以重新创建异步调用,您可以完全消除超时并立即解决/拒绝。调用
link方法的唯一好方法是通过这些编译指令,但您始终可以将可测试的功能拆分为单独的controller。
标签: javascript angularjs unit-testing jasmine