[英]How to unit test an angular directive
对角度指令进行单元测试不是很困难,但是我发现有不同的方法可以执行它。
出于本文的目的,让我们假设以下指令
angular.module('myApp')
.directive('barFoo', function () {
return {
restrict: 'E',
scope: true,
template: '<p ng-click="toggle()"><span ng-hide="active">Bar Foo</span></p>',
controller: function ($element, $scope) {
this.toggle() {
this.active = !this.active;
}
}
};
});
现在我可以想到两种方法对此进行单元测试
方法1:
describe('Directive: barFoo', function () {
...
beforeEach(inject(function($rootScope, barFooDirective) {
element = angular.element('<bar-foo></bar-foo>');
scope = $rootScope.$new();
controller = new barFooDirective[0].controller(element, scope);
}));
it('should be visible when toggled', function () {
controller.toggle();
expect(controller.active).toBeTruthy();
});
});
方法2:
beforeEach(inject(function ($compile, $rootScope) {
element = angular.element('<bar-foo></bar-foo>');
scope = $rootScope.$new();
$compile(element)(scope);
scope.$digest();
}));
it ('should be visible when toggled', function () {
element.click();
expect(element.find('span')).not.toHaveClass('ng-hide');
});
因此,我很好奇这两种方法的优缺点以及哪种方法最可靠?
这是测试AngularJS指令的方法:
describe('Directive: barFoo', function () { var createElement, element, parentScope, directiveScope; beforeEach(module('myApp')); beforeEach(inject(function($injector) { var $compile = $injector.get('$compile'); var $rootScope = $injector.get('$rootScope'), parentScope = $rootScope.$new(); parentScope.paramXyz = ... <-- prepare whatever is expected from parent scope createElement = function () { element = $compile('<bar-foo></bar-foo>')(parentScope); directiveScope = element.isolateScope(); parentScope.$digest(); $httpBackend.flush(); <-- if needed }; })); it('should do XYZ', function() { parentScope.xyz = ... <-- optionnal : adjust scope according to your test createElement(); expect(...) <-- whatever, examples : var submitButton = element.find('button[type="submit"]'); expect( submitButton ).to.have.value('Validate'); expect( submitButton ).to.be.disabled; submitButton.click(); });
我喜欢做的是像这个虚拟示例一样创建测试的故事。
'use strict';
describe('app controller', function() {
var scope;
...
beforeEach(angular.mock.module('MyModule'));
it('should have properties defined', function() {
expect(scope.user).toEqual(user);
...
});
it('should have getFaqUrl method', function() {
expect(scope.getFaqUrl).toEqual(refdataService.getFaqUrl);
});
it('should signout and delete user data from local storage', function() {
...
});
});
因此,我想您只是没有在第二个示例中说明它,但是如果您这样做了,请在测试时始终使用describe外壳,这是一个很好的做法。
至于测试本身,我建议您避免使用显式调用scope。$ digest()的方法,特别是因为对于您的测试而言,它似乎不必要。
很快,我会去方法1。
我发现第一种方法更“正确”,因为它不依赖于单击事件。 我认为,如果要测试元素的单击及其效果,则应使用量角器,而仅将茉莉用于单元测试。 这样,您将在单元测试和UI测试之间实现很好的分离。
这也使测试更具可维护性。 例如,如果您决定在第二种方法中悬停而不是单击时toggle
,那么您还必须更新测试。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.