angularjs:测试基于控制器的指令

时间:2015-09-18 10:47:53

标签: angularjs angularjs-directive angularjs-scope karma-jasmine

我通过ngController将指令绑定到控制器,如下所示:

app.directive('myDirective', ['myService',
    function(myService) {
        return {
            restrict: 'E',
            replace: true,
            scope: true,
            require: "^ngController",
            templateUrl: 'template.html',
            link: {
                pre: function (scope, elem, attrs, controller) {
                    scope.list = [];
                    myService.getData().then(function (response) {
                        scope.list = response.data;
                    });
                },
                post: function (scope) {
                    for (var rec = 0; rec < scope.list.length; rec++) {
                        if (scope.list[rec].key2 == 'd') {
                            // Do something here..
                        }
                    }
                }
            }
        };
    }
]);

使用样本控制器(因为该指令在多个地方使用):

app.controller('testController', [
    function () {
        var testCtrl = this;
    }
]);

该指令的测试用例是:

describe('myDirective', function () {
    var element, scope, ctrl;
    beforeEach(angular.module('myModule'));
    beforeEach(inject(function ($rootScope, $compile, $controller, $httpBackend) {
        mockBackEnd = $httpBackend;

        // Call to myService.getData()
        mockBackEnd.expectGET('/module/service/api').respond({
            values: [{key1: a, key2: b}, {key1: c, key2: d}]
        });

        element = angular.element('<div ng-controller="testController"><my-directive></my-directive></div>');
        ctrl = $controller('testController', {});
        scope = $rootScope.$new();
        compile(element)(scope);
        mockBackEnd.flush();
        scope.$digest();
    }));

    it('Test for response', function () {
        expect(scope.list.length).toBe(2);
    });
});

我收到错误消息:PhantomJS 1.9.8 myDirective FAILED TypeError: 'undefined' is not an object (evaluating 'scope.list.length')

进一步检查:在检查$digest()发生的位置时,发现在post:链接功能中,scope.list对象显示为[],因为它应该是返回值来自服务。

该指令在模块中工作正常,但会在测试用例中引发问题。

我在这里做错了什么?在业力方面需要一些帮助。

2 个答案:

答案 0 :(得分:0)

对不起@curlyreggie,当我查看你的代码时,我真的不明白为什么它如此复杂?

为什么不将数据作为数组或JSON对象传递给指令范围?

为什么要使用ng-controller指令?

无论如何,要在测试中向你的指令添加一些AngularJS函数,请使用angular.element()。

var compile = $compile; // is missing in your code
scope = $rootScope.$new();

var element = angular.element('<my-directive ng-controller="testController">Add all parameters, as you usually do in your html, if missing anything</my-directive>');
compile(element)(scope);
scope.$digest();

// Get the isolate scope for the directive
var isolatedScope = element.isolateScope();
console.log("isolatedScope", isolatedScope);

&&#39; mockBackEnd&#39;通常我这样注射:

beforeEach(inject(function ($rootScope, $compile, $controller, $injector) {
   mockBackEnd = $injector.get('$httpBackend');
   .....
}

不确定这是否有效,但至少我试图帮助你:)

答案 1 :(得分:0)

好吧,我使用了一些帮助from the community来解决它。

事实是,根据这里的评论/答案,我正在进行错误的测试。实际的测试用例设置应该是。

describe('myDirective', function () {
   var element, scope, ctrl, directiveScope;
   beforeEach(angular.module('myModule'));
   beforeEach(inject(function ($rootScope, $compile, $controller, $httpBackend) {
      mockBackEnd = $httpBackend;

      // Call to myService.getData()
      mockBackEnd.expectGET('/module/service/api').respond({
        values: [{key1: a, key2: b}, {key1: c, key2: d}]
      });

      ctrl = $controller('testController', {});
      scope = $rootScope.$new();
      element = $compile(angular.element('<div ng-controller="testController"><my-directive></my-directive></div>'))(scope);
      directiveScope = element.find('my-directive').scope();
      scope.$digest();
      mockBackEnd.flush();
}));

it('Test for response', function () {
    expect(directiveScope.list.length).toBe(2);
});

我在这里摆弄父范围,指令的范围无法从外部访问。使用element.find().scope()首先获取该范围并将其用于方便。

修改为新代码后,pre-linkpost-link函数按预期执行。