需要控制器测试指令 [英] Testing directives that require controllers

查看:128
本文介绍了需要控制器测试指令的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以,我没有看到另一个问题:<一href=\"http://stackoverflow.com/questions/16514045/how-to-mock-required-directive-controller-in-directive-ut\">How嘲笑的指令UT 所需的指令控制器,它基本上是我的问题,但它似乎是回答这个线程改变你的设计。我想,以确保有没有办法做到这一点。我声明这是儿童使用的指令控制器的指令。我现在想写为孩子指令测试,茉莉,但我不能让他们在测试中编译,因为它们依赖于控制器。这里是什么样子:

So I did see another question: How to mock required directive controller in directive UT which is basically my problem but it seems the answer to this thread was "change your design." I wanted to make sure there is no way to do this. I have a directive that declares a controller which is used by children directives. I am now trying to write jasmine tests for the children directive but I cant get them to compile in the tests because they are dependent on the controller. Here is what it looks like:

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,
            restrict: 'A',
            scope: {
                config: '='
            },
            template:
                '...',
            require: "^address360",
            link: function(scope, element, 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();
}));

有没有办法对我来说,测试与茉莉,如果是这样子的指令,我缺少什么?即使我能考指令本身不带控制器的功能我会很高兴。

Is there no way for me to test the sub directive with jasmine and if so, what am I missing? Even if I could test the directive itself without the controller functions I would be happy.

推荐答案

我能想到的两种方法:

1)用两个指令

让我们假设有下列指令:

Let's assume we have the following directives:

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

app.directive('bar', function() {
  return {
    restrict: 'E',
    require: '^foo',
    link: function(scope, element, attrs, foo) {
      scope.callFoo = function(x, y) {
        scope.sum = foo.add(x, y);
      }
    }
  };
});

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

In order to test the callFoo method, you can simply compile both directives and let bar use foo's implementation:

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);
});    

工作Plunker

2)模拟Foo的控制器退出

这一个是不是很简单,有点棘手。你可以使用 element.controller()来获取元素的控制,并与茉莉嘲笑它:

This one is not quite straightforward and a little tricky. You could use element.controller() to get the controller of an element, and mock it out with 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);
  });

工作Plunker

最棘手的部分来了,当一个指令使用其他的控制器在其链接马上功能:

The tricky part comes up when one directive uses the other's controller right away in its link function:

app.directive('bar', function() {
  return {
    restrict: 'E',
    require: '^foo',
    link: function(scope, element, attrs, foo) {
      scope.sum = foo.add(parseInt(attrs.x), parseInt(attrs.y));
    }
  };
});

在这种情况下,你需要单独编译每个指令,所以你可以嘲笑第一个出第二个使用它之前:

In this case you need to compile each directive individually so you can mock the first one out before the second one uses it:

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);
});

工作Plunker

第一种方法比第二种方法更简单,但它依赖于第一指令,即执行,你不是单元测试的东西。在另一方面,虽然嘲讽指令的控制器也不是那么容易,它可以让你在测试更多的控制权,并删除第一个指令的依赖。所以,明智的选择。 :)

The first approach is way easier than the second one, but it relies on the implementation of the first directive, i.e, you're not unit testing things. On the other hand, although mocking the directive's controller isn't so easy, it gives you more control over the test and removes the dependency on the first directive. So, choose wisely. :)

最后,我不知道一个更简单的方法做上述所有。如果有人更好的方法的人都知道,请提高我的答案。

Finally, I'm not aware of an easier way to do all of the above. If anyone knows of a better approach, please improve my answer.

这篇关于需要控制器测试指令的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆