访问AngularJs指令控制器

时间:2016-10-10 09:02:28

标签: javascript angularjs unit-testing jasmine karma-runner

我在使用jasmine和karma testrunner进行单元测试的指令访问我的控制器时遇到了一些问题。该指令如下所示:

指令

angular.module('Common.accountSearch',['ngRoute'])

    .directive('accountSearch', [function() {
        return {
            controllerAs: 'ctrl',
            controller: function ($scope, $element, $routeParams, $http) {

                this.setAccount = function () {
                    var response = { AccountId : $scope.ctrl.searchedAccount.AccountId }
                    $scope.callback(response)
                }


                this.getAccounts = function(searchText){
                    return $http.get('/api/CRMAccounts', {
                        params: {
                            retrievalLimit: 10,
                            search: searchText
                        }
                    }).then(function(response){
                        return response.data;
                    });

                }

            },
            scope : {
                config : '=',
                values : '=',
                callback : '='
            },
            templateUrl : '/common/components/account-search/account-search.html',
            restrict : 'EAC'
        }
    }]);

到目前为止,这是测试用例文件,我相信一切正常(我希望):

测试用例文件:

    describe("Account search directive logic tests", function (){
  var element,$scope,scope,controller,template

  beforeEach(module("Common.accountSearch"))


  beforeEach(inject( function (_$compile_, _$rootScope_,_$controller_,$templateCache) {
    template = $templateCache.get("components/account-search/account-search.html")
    $compile = _$compile_;
    $rootScope = _$rootScope_;
    $controller = _$controller_;
    scope = $rootScope.$new();
    element = $compile(template)(scope)
    ctrl = element.controller
    scope.$digest();
  //  httpBackend = _$httpBackend_;
  }));




  it(" sets the account and calls back.", inject(function () {

    console.log(ctrl)
    expect(ctrl).toBeDefined()
   }));
  //httpBackend.flush()
});

我设法将指令的控制器(我认为)打印到控制台,该控制台返回以下不明确的消息:

LOG: function (arg1, arg2) { ... }

我无法访问指令中的任何函数或属性,因为它们都返回“未定义”,我做错了什么?

3 个答案:

答案 0 :(得分:6)

如此接近!

element.controller是一个函数,需要传递您试图获取控制器的指令的名称。在这种情况下,它将是

ctrl = element.controller("accountSearch");

答案 1 :(得分:4)

指令的控制器实际上是完全可注入的 - 您可以通过名称来引用控制器,而不是提供构造函数。请参阅Angular的指令定义对象docs:https://docs.angularjs.org/api/ng/service/ $ compile#directive-definition-object

如果你想对控制器进行单元测试,你可以这样做:

<强> common.accountSearch.js

angular.module('Common.accountSearch', [])
  .directive('accountSearch', [function () {
      return {
          controller: 'accountSearchCtrl',
          scope: {
              config    : '=',
              values    : '=',
              callback  : '='
          },
          templateUrl : '/common/components/account-search/account-search.html',
          restrict: 'EAC'
      }
  }])
  .controller('accountSearchCtrl', ['$scope', function ($scope) {
      $scope.setAccount = function () {
          var response = {
              AccountId: $scope.ctrl.searchedAccount.AccountId
          };
          $scope.callback(response);
      }

      $scope.getAccounts = function (searchText) {
          // Code goes here...
      }
  }]);

<强> common.accountSearch-spec.js

describe("Account search directive logic tests", function () {    
    var controller, scope;

    beforeEach(module("Common.accountSearch"));

    beforeEach(inject(function (_$controller_, _$rootScope_) {        
        $rootScope = _$rootScope_;
        scope = $rootScope.$new();
        controller = _$controller_('accountSearchCtrl', { '$scope': scope });        
    }));

    it(" sets the account and calls back.", function () {
        expect(controller).toBeDefined();
    });
});

通过这种方式,您可以将控制器直接注入茉莉花测试,就像其他任何控制器一样。

希望这有帮助。

答案 2 :(得分:0)

element.controller是AngularJS jqLit​​e的另一种方法,因此当您记录它时,您会看到jqLit​​e方法.toString()。你应该调用它并获得一个指令控制器。 Element controller manual