How to mock required directive controller in direc

2019-07-29 04:27发布

According to AngularJS doc a/the directive controller is:

instantiated before the pre-linking phase and it is shared with other directives if they request it by name (see require attribute). This allows the directives to communicate with each other and augment each other's behavior.

This sounds great and useful in a case where UI view is composed of container and widget, widget's link func can be passed in the container directive controller via declarative approach require:^cotnainerDirective. This gives an alternative way to callback container behavior instead of communication relying on events.

For example, a widget directive which is requiring container controller as below:

angular.module('platform').directive('widget', [ function ( ) {
    return {
        restrict: 'E',
        transclude: true,
        require: '?^container',
        replace: true,
        scope: {
            layout: '=',
            model: '='
        },
        templateUrl: 'js/modules/platform/templates/form-tmpl.html',
        link: function (scope, element, iAttrs, requiredCtrl) {
            if(requiredCtrl && requiredCtrl.fooMethod){
                ....
            }
        }
    };
}]);

the code inside link function will do additional work if the widget is living inside a container. The code is working fine. However, when coming to unit testing the widget directive, it is hard to think about a good way to send in a mock container directive controller simply because it is not injected via Angular $injector service.

Probably, I need to write the UT from container perspective, but this somehow involves too much preparation work needed for bootstrapping the container directives. Anyone encounter this before and can share some good points here?

2条回答
我只想做你的唯一
2楼-- · 2019-07-29 05:12

It turns out if I want to unit test the widget directive, it has to be loosely decoupled from container, in that case using "require" is not a good idea since it is actually making the widget directive tightly dependents on the container. I have changed my design to use event-driven communication btw widget and container, in this way i can simply mock event listener to watch on the events sent by widget directive in UT.

查看更多
3楼-- · 2019-07-29 05:27

You could define a <fake-parent> HTML element in your test and then add a containerControllerMock to its data store under $containerController key. I explain this approach for testing child directive in isolation here: https://demisx.github.io/angularjs/unit-testing/2014/10/28/unit-testing-angular-child-directive-that-requires-parent.html

查看更多
登录 后发表回答