Angularjs 如何在指令链接中测试函数

Angularjs 如何在指令链接中测试函数,angularjs,angularjs-directive,jasmine,karma-runner,karma-jasmine,Angularjs,Angularjs Directive,Jasmine,Karma Runner,Karma Jasmine,我有一个指令,我正试图为其编写一些单元测试: return { restrict: 'E', replace: true, controllerAs: 'vm', transclude: true, template: '<ul>' + '<li ng-show="vm.hideItem">Home</li>' + '<li ng-

我有一个指令,我正试图为其编写一些单元测试:

return {
    restrict: 'E',
    replace: true,
    controllerAs: 'vm',
    transclude: true,
    template:   '<ul>' +
                    '<li ng-show="vm.hideItem">Home</li>' +
                    '<li ng-show="vm.hideItem">Products</li>' +
                    '<li ng-show="!vm.hideItem">Cart</li>' +
                    '<li ng-show="vm.hideItem">Contact Us</li>' +
                '</ul>',  
    link: function(scope, element, attrs, vm) {

        function getData(index) {
            if (index){
                vm.hideItem = true
            }
            else {
                var li = element.find("li");
                li.attr("context-driven", "");
            }
        }

        function getIndex(){
            index = myService.getIndex();
            getData(index);
        }

        getIndex();

    },
    controller: function(){}
};
返回{
限制:'E',
替换:正确,
controllerAs:'vm',
是的,
模板:“
    ”+ “
  • 主页”+ “
  • 产品”+ “
  • 购物车
  • ”+ “
  • 请与我们联系”+ “
”, 链接:函数(范围、元素、属性、vm){ 函数getData(索引){ 如果(索引){ vm.hideItem=true } 否则{ var li=元素。查找(“li”); attr(“上下文驱动的”,”); } } 函数getIndex(){ index=myService.getIndex(); 获取数据(索引); } getIndex(); }, 控制器:函数(){} };
我有以下几项通过:

describe('<-- myDirective Spec ------>', function () {

    var scope, $compile, element, myService;

    beforeEach(angular.mock.module('MyApp'));

    beforeEach(inject(function (_$rootScope_, _$compile_, _myService_) {
        scope = _$rootScope_.$new();
        $compile = _$compile_;
        myService = _myService_;

        var html = '<my-directive></my-directive>';
        element = $compile(angular.element(html))(scope);
        scope.$digest();
    }));

    it('should return an unordered list', function () {
        var ul = element.find('ul');
        expect(ul).toBeDefined();
    });
描述(“”,函数(){
变量范围,$compile,元素,myService;
beforeach(angular.mock.module('MyApp'));
beforeach(注入(函数($rootScope,$compile,u myService){
scope=\$rootScope\$new();
$compile=\$compile;
myService=\u myService\u;
var html='';
element=$compile(angular.element(html))(范围);
范围。$digest();
}));
它('应返回无序列表',函数(){
var ul=元素。find('ul');
期望(ul.toBeDefined();
});

如何测试
getIndex
getData
的调用并确保调用了
myService

指令测试成功的关键是将所有与视图相关的逻辑移动到控制器,即

    this.getIndex = function () {
        index = myService.getIndex();
        getData(index);
    }
在spec中编译元素后,可以使用

var ctrl = element.controller('myDirective');
spyOn(ctrl, 'getIndex').and.callThrough();

编写规范的好处是它们显示了设计缺陷。在当前情况下,这是
getData
中的DOM手动操作。代码中不清楚
上下文驱动的属性是什么,但同样的事情必须在Angular(数据绑定)而不是jQuery(DOM操作)中实现为了测试友好而流行。

如果不重构代码,就不可能按照您的要求去做。同样,应该定义代码编写方式的是可测试性原因,而不是相反。测试不友好的代码不会得到100%的测试覆盖率(测试myService.getIndex调用是这里可以完成的全部工作)。