angularjs – 需要控制器的测试指令

前端之家收集整理的这篇文章主要介绍了angularjs – 需要控制器的测试指令前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
所以我没有看到另一个问题: How to mock required directive controller in directive UT这基本上是我的问题,但似乎这个线程的答案是“改变你的设计。我想确保没有办法做到这一点。我有一个指令,声明一个控制器被儿童指令使用。我现在试图写儿童指令的茉莉花测试,但我不能让他们在测试中编译,因为他们依赖于控制器。这是它的外观:
addressModule.directive('address',['$http',function($http){
        return {
            replace: false,restrict: 'A',scope: {
                config: '='
            },template:   '<div id="addressContainer">' +
                            '<div ng-if="!showAddressSelectionPage" basic-address config="config"/>' +
                            '<div ng-if="showAddressSelectionPage" address-selector addresses="standardizedAddresses"/>' +
                        '</div>',controller: function($scope)
            {
                this.showAddressInput = function(){
                    $scope.showAddressSelectionPage = false;
                };

                this.showAddressSelection = function(){
                    $scope.getStandardizedAddresses();
                };

                this.finish = function(){
                    $scope.finishAddress();
                };
            },link: function(scope,element,attrs) {
              ...
            }
       }
}])

儿童指示:

addressModule.directive('basicAddress360',['translationService',function(translationService){
        return {
            replace: true,template:
                '...',require: "^address360",attrs,addressController){
            ...
            }
       }
}])

茉莉花试验:

it("should do something",inject(function($compile,$rootScope){
            parentHtml = '<div address/>';
            subDirectiveHtml = '<div basic-address>';

            parentElement = $compile(parentHtml)(rootScope);
            parentScope = parentElement.scope();
            directiveElement = $compile(subDirectiveHtml)(parentScope);
            directiveScope = directiveElement.scope();
            $rootScope.$digest();
}));

有没有办法让我用茉莉花测试sub指令,如果是这样,我错过了什么?即使我可以测试指令本身没有控制器的功能,我会很高兴。

我可以想到两种方法

1)使用这两个指令

让我们假设我们有以下指令:

app.directive('foo',function() {
  return {
    restrict: 'E',controller: function($scope) {
      this.add = function(x,y) {
        return x + y;
      }
    }
  };
});

app.directive('bar',require: '^foo',foo) {
      scope.callFoo = function(x,y) {
        scope.sum = foo.add(x,y);
      }
    }
  };
});

为了测试callFoo方法,你可以简单地编译这两个指令,让bar使用foo的实现:

it('ensures callFoo does whatever it is supposed to',function() {
  // Arrange
  var element = $compile('<foo><bar></bar></foo>')($scope);
  var barScope = element.find('bar').scope();

  // Act
  barScope.callFoo(1,2);

  // Assert
  expect(barScope.sum).toBe(3);
});

Working Plunker

2)模拟foo的控制器

这个不是很直接,有点棘手。你可以使用element.controller()获取元素的控制器,并用Jasmine模拟它:

it('ensures callFoo does whatever it is supposed to',function() {
    // Arrange
    var element = $compile('<foo><bar></bar></foo>')($scope);
    var fooController = element.controller('foo');
    var barScope = element.find('bar').scope();
    spyOn(fooController,'add').andReturn(3);

    // Act
    barScope.callFoo(1,2);

    // Assert
    expect(barScope.sum).toBe(3);
    expect(fooController.add).toHaveBeenCalledWith(1,2);
  });

Working Plunker

当一个指令在其链接函数中立即使用另一个控制器时,棘手的部分出现:

app.directive('bar',foo) {
      scope.sum = foo.add(parseInt(attrs.x),parseInt(attrs.y));
    }
  };
});

在这种情况下,您需要单独编译每个指令,以便在第二个使用它之前模拟第一个指令:

it('ensures callFoo does whatever it is supposed to',function() {
  // Arrange
  var fooElement = $compile('<foo></foo>')($scope);
  var fooController = fooElement.controller('foo');
  spyOn(fooController,'add').andReturn(3);

  var barElement = angular.element('<bar x="1" y="2"></bar>')
  fooElement.append(barElement);

  // Act
  barElement = $compile(barElement)($scope);
  var barScope = barElement.scope();

  // Assert
  expect(barScope.sum).toBe(3);
  expect(fooController.add).toHaveBeenCalledWith(1,2);
});

Working Plunker

第一种方法比第二种方法更容易,但它依赖于第一个指令的实现,即,你不是单元测试的东西。另一方面,虽然嘲笑指令的控制器不是那么容易,它给你更多的控制测试和删除对第一个指令的依赖。所以,选择明智。

猜你在找的Angularjs相关文章