我在使用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) { ... }
我无法访问指令中的任何函数或属性,因为它们都返回“未定义”,我做错了什么?
答案 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 jqLite的另一种方法,因此当您记录它时,您会看到jqLite方法.toString()
。你应该调用它并获得一个指令控制器。 Element controller manual