簡體   English   中英

如何對角度指令進行單元測試

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM