经过多次研究,我无法正确测试Angular指令,因为我无法访问其控制器内的函数。
这是指令代码:
angular.module('app').
directive("accordionItem", function () {
return{
restrict: 'E',
replace: true,
templateUrl: function (elem, attr) {
return 'partials/invoice/' + attr.temp + '.html';
},
scope: {
invoice: '=',
temp: '@'
},
controller: function ($scope, listSelectionService, $state) {
$scope.selectItem = function () {
if ($scope.isOpen()) {
listSelectionService.selectedItem = -1;
}
else {
listSelectionService.selectedItem = $scope.invoice;
}
};
$scope.isOpen = function () {
return listSelectionService.selectedItem === $scope.invoice;
};
$scope.showFaturasSubscription = function () {
$state.go('app.ultimasFaturasSubscription', {subscriptionId: $scope.invoice.subscriptionId});
};
}
};
});
我的测试:
describe('Invoice', function() {
var $scope = {}, controller, $httpBackend, $controller, form, element;
beforeEach(module('app'));
describe('Directives', function() {
beforeEach(inject(function($compile, $rootScope, _$httpBackend_, _$controller_) {
$httpBackend = _$httpBackend_;
$httpBackend.expect('GET', 'data/translation/?lang=pt').respond(200, []);
$httpBackend.when('GET', 'partials/invoice/undefined.html').respond(200, []);
$httpBackend.when('GET', 'partials/templates/loading.html').respond(200, []);
$httpBackend.when('GET', 'partials/invoice/invoiceContent.html').respond(200, []);
$scope = $rootScope.$new();
$controller = _$controller_;
form = $compile("<accordion-item temp='invoiceContent'></accordion-item>")($scope);
$scope.$digest();
}));
it('should submitButtonDisabled', inject(function($injector) {
var listSelectionService = $injector.get("listSelectionService");
$scope.selectItem();
expect(listSelectionService.selectedItem).toBe(-1);
}));
});
});
根据我读过的许多文件,在$ digest()函数之后,我们可以访问指令的控制器。这没有发生,因为它给我以下错误:
TypeError: $scope.selectItem is not a function at null.<anonymous> (http://localhost:8234/spec/invoice/invoiceDirectivesSpec.js:27:20) at Object.invoke (http://localhost:8234/src/main/webapp/vendor/angular/angular.js:4452:17) at workFn (http://localhost:8234/src/main/webapp/vendor/angular-mocks/angular-mocks.js:2420:20) at jasmine.Block.execute (http://localhost:8234/?:1164:19) at jasmine.Queue.next_ (http://localhost:8234/?:2196:33) at jasmine.Queue.start (http://localhost:8234/?:2149:10) at jasmine.Spec.execute (http://localhost:8234/?:2476:16) at jasmine.Queue.next_ (http://localhost:8234/?:2196:33) at jasmine.Queue.start (http://localhost:8234/?:2149:10) at jasmine.Suite.execute (http://localhost:8234/?:2621:16) Error: Declaration Location at window.inject.angular.mock.inject (http://localhost:8234/src/main/webapp/vendor/angular-mocks/angular-mocks.js:2391:25) at null.<anonymous> (http://localhost:8234/spec/invoice/invoiceDirectivesSpec.js:25:43) at jasmine.Env.describe (http://localhost:8234/?:919:23) at describe (http://localhost:8234/?:703:29) at null.<anonymous> (http://localhost:8234/spec/invoice/invoiceDirectivesSpec.js:10:5) at jasmine.Env.describe (http://localhost:8234/?:919:23) at describe (http://localhost:8234/?:703:29) at http://localhost:8234/spec/invoice/invoiceDirectivesSpec.js:5:1
任何帮助都会非常感激。
答案 0 :(得分:5)
我通常以与常规控制器相同的方式测试指令控制器。
在您的指令中,您已将控制器内联定义为指令的一部分。相反,像对待与视图一起使用的控制器一样定义它:
在模块上注册控制器:
angular.module('app').controller('DirectiveController', function($scope) { ... });
在指令配置中引用控制器:
controller: 'DirectiveController'
测试控制器:
这将取代或补充实际的指令测试。在指令之外测试控制器要简单得多,您不必担心实例化指令或处理DOM元素。通常情况下,如果指令的模板足够简单,我甚至不用担心指令测试而只是测试控制器。简单的例子:
var controller, scope;
beforeEach(inject(function($rootScope, $controller) {
scope = $rootScope.$new();
controller = $controller('DirectiveController', {$scope: scope});
}));
describe('controller', function() {
it('exists', function() {
expect(controller).toBeDefined();
expect(controller).not.toBeNull();
});
});