2016-08-11 39 views
1

我花了一大堆时间试图单元测试一个指令,该指令在控制器内生成/跟踪一个承诺,这是如何完成的一个例子可以在这里看到: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()永远不会被调用。我已经尝试了很多变化来强制$摘要,但似乎没有完成承诺。

+0

我是一个角度n00b,有没有办法将一个指令注入测试并直接调用'link'方法,或者你是否需要编译和消化它来评估它? – dm03514

+0

为最小可行的测试,是否有可能从'saveCtrl'中删除$超时,所以承诺立即解决?并通过不使用随机的??从测试中消除非确定性。理想情况下,可以有2个单独的测试,一个“拒绝”分支和一个“分支”分支? – dm03514

+0

@ dm03514当然,我将它添加到实际指令中的功能以重新创建异步调用,您可以完全删除超时并立即解决/拒绝。调用'link'方法的唯一好方法就是通过这些编译的指令,但是你总是可以将可测试的功能分割成单独的'controller'。 – spaceribs

回答

0

想我明白了。 https://plnkr.co/edit/CBvrZo4g9LjJC61VV0wp

```

$scope.saveCtrl = function(data) { 
    return $q(function(resolve, reject) { 
     setTimeout(function() { 
      if (Math.round(Math.random())) { 
       var id = parseInt(Math.random() * 100); 
       resolve(id); 
      } else { 
       reject(new Error()); 
      } 
      elementScope.$apply(); 
      $scope.$apply(); 
     }, 100); 
    }); 
}; 

```

有在管线39未定义var和角超时被奇怪行为。这应该导致指令的完整流程在超时时间内进行测试。我认为可能不需要超时,因为您可以假设即时超时情况而不会丢失任何测试。

+0

医管局,我从来没有猜到为模拟的承诺增加额外的摘要,疯了! – spaceribs