How to inject a controller into a directive when unit-testing

左心房为你撑大大i 提交于 2020-01-22 10:33:16

问题


I want to test an AngularJS directive declared like this

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

In the test I would like to inject (or override) the controller, so that I can test just the other parts of the directive (e.g. the template). The customerController can of course be tested separately. This way I get a clean separation of tests.

  • I have tried overriding the controller by setting the controller property in the test.
  • I have tried injecting the customController using $provide.
  • I have tried setting ng-controller on the html directive declaration used in the test.

I couldn't get any of those to work. The problem seems to be that I cannot get a reference to the directive until I have $compiled it. But after compilation, the controller is already set up.

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

回答1:


I think there is a simpler way than the accepted answer, which doesn't require creating a new module.

You were close when trying $provide, but for mocking controllers, you use something different: $controllerProvider. Use the register() method in your spec to mock out your controller.

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



回答2:


One way is to define a new module (e.g. 'specApp') that declares your app (e.g. 'myApp') as a dependency. Then register a 'customerController' controller with the 'specApp' module. This will effectively "hide" the customerController of 'myApp' and supply this mock-controller to the directive when compiled.
E.g.:

Your app:

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

Your spec:

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

See, also, this working demo.



来源:https://stackoverflow.com/questions/21218273/how-to-inject-a-controller-into-a-directive-when-unit-testing

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!