如何在单元测试时将控制器注入指令中

时间:2014-01-19 14:53:35

标签: angularjs unit-testing dependency-injection controller directive

我想测试一个像这样声明的AngularJS指令

app.directive('myCustomer', function() {
    return {
      template: 'cust.html'
      controller: 'customerController'
    };
  });

在测试中我想注入(或覆盖)控制器,这样我就可以只测试指令的其他部分(例如模板)。 customerController当然可以单独测试。这样我就可以清楚地分离测试。

  • 我尝试通过在测试中设置controller属性来覆盖控制器。
  • 我尝试使用customController注入$provide
  • 我尝试在测试中使用的html指令声明上设置ng-controller

我无法让任何人工作。问题似乎是在我有$compile之前我无法获得对该指令的引用。但是在编译之后,控制器已经设置完毕。

 var element = $compile("<my-customer></my-customer>")($rootScope);

2 个答案:

答案 0 :(得分:10)

一种方法是定义一个新模块(例如'specApp'),将您的应用(例如'myApp')声明为依赖项。然后使用'specApp'模块注册'customerController'控制器。这将有效地“隐藏”'myApp'的customerController,并在编译时将该模拟控制器提供给指令 E.g:

您的应用

var app = angular.module('myApp', []);
...
app.controller('customerController', function ($scope,...) {
    $scope = {...};
    ...
});
app.directive('myCustomer', function () {
    return {
        template: 'cust.html',
        controller: 'customerController'
    };
});

您的规范

describe('"myCustomer" directive', function () {
    $compile;
    $newScope;

    angular.module('specApp', ['myApp'])
    /* Register a "new" customerController, which will "hide" that of 'myApp' */
    .controller('customerController', function ($scope,...) {
        $scope = {...};
        ...
    });

    beforeEach(module('specApp'));

    it('should do cool stuff', function () {
        var elem = angular.element('<div my-customer></div>');
        $compile(elem)($newScope);
        $newScope.$digest();
        expect(...
    });
});

另请参阅此 working demo

答案 1 :(得分:6)

我认为有一种比接受的答案更简单的方法,它不需要创建新的模块。

在尝试$provide时你很接近,但是对于模拟控制器,你会使用不同的东西:$controllerProvider。使用规范中的register()方法模拟控制器。

 
beforeEach(module('myApp', function($controllerProvider) {
    $controllerProvider.register('customerContoller', function($scope) {
        // Controller Mock
    });
});