如何在一个指令的链接函数中testing行为

在我的一些指令中,我将函数添加到作用域以处理指令的特定逻辑。 例如:

link: function(scope, element, attrs) { scope.doStuff = function() { //do a bunch of stuff I want to test } } 

我如何去testing这个function? 我search了一下如何testing一个指令,但是我发现的东西更多的是testing元素的变化。 我可以在每次testing之前编译我的指令,但每次都会消除我的范围。 我想testing作为我的范围更改中的属性函数。

有什么办法来获得从指令定义中返回的对象吗? 然后,我可以直接调用链接函数,并testing范围中定义的每个函数的行为。 有没有更好的方法来做到这一点?

我正在使用Jasmine来运行我的testing,我想在我的范围设置在describefunction,所以我可以有多个function相同的范围数据。

基本上,不是testing链接函数本身,而是以编程方式testing指令的结果。 你会做的是写出一个string的指令,并使用$compile有angular度的过程。 然后你testing输出,以确保一切正确连接。

Angular的源码充满了如何做到这一点的很好的例子…例如Angular对ngRepeat指令的testing

你可以看到他们在做的是设置指令,改变范围(在这个例子中是$rootScope ),确保它是$digest ed,然后testing它输出的DOM,以确保所有的东西都连接正确。 如果指令正在改变,你也可以testing范围内的内容。

ngClick的testing也非常有趣,因为它显示了浏览器交互的testing,它对范围有影响。

为了完整起见,下面是ngClicktesting中的一个片段,我认为这个片段testing指令相当好:

  it('should get called on a click', inject(function($rootScope, $compile) { element = $compile('<div ng-click="clicked = true"></div>')($rootScope); $rootScope.$digest(); expect($rootScope.clicked).toBeFalsy(); browserTrigger(element, 'click'); expect($rootScope.clicked).toEqual(true); })); 

所以在你的scope.doStuff函数的情况下,我不会testing它在做什么 ,就像我testing它在范围上受到什么影响一样,并且随后会影响DOM元素。

我解决这个问题有点不同。

如果你的指令中有一个非常简单的链接函数,而且你并不需要第三个参数( attrs ),那么只需要去掉链接函数,并为其指定一个控制器

 app.directive('loadIndicator', function() { return { restrict: 'E', replace: true, templateUrl: 'blahblah/indicator.html', controller: 'LoadIndicatorController' }; }); 

就像你在指令的链接函数中有作用域和元素的参数一样,这两个参数可以作为$ scope$ element注入到一个易于testing的控制器中。

如果你有能力创build控制器和unit testing这些控制器,那么这将是很容易做到的。

如果需要,可以直接对指令的链接方法进行unit testing。 查看angular冰模块的unit testing器:“testing指令configuration”

http://bverbist.github.io/angular-ice/#/unitTester

示例用法: https : //github.com/bverbist/angular-ice/blob/master/app/components/icebank/bank-account-number-directive_link_test.js

在你的情况下,你可以保留对传递给指令链接方法的作用域对象的引用,然后你可以直接testing该作用域上的doStuff函数。

正如在回复@sqlexception的评论中所述。 你真的需要处理指令的范围,这是不难的。 你不想做的是修改你的代码来满足你的testing,因为它应该是相反的。

为了得到这个指令的范围就像这样编译:

var element = $compile(<directive's html>).($scope)

其中$scope是用$scope = $rootScrope.$new() 。 现在我们可以通过执行element.scope()来获得隔离范围

我刚刚写了一篇关于在这里find的简短的博客文章testing一个链接函数与一个沉重的帮助: