使用templateUrl和triggerHandler对Angular指令进行单元测试

时间:2017-04-11 12:15:01

标签: angularjs unit-testing karma-runner

我尝试为我的示例指令编写单元测试,但如果我在template上替换templateUrl,那么element.triggerHangler不会触发指令事件,我不明白为什么。

我的指示

'use strict';

angular.module('app')
  .directive('chatEditor', function() {
    return {
      scope: {
        onAdd: '&'
      },
      templateUrl: 'chat/chat-editor.directive.html',
      /*template: '<div></div>'*/
      link: function(scope, element, attrs) {
        element.on('click', function() {
          scope.onAdd({message: 'test'});
      });
    }
  }
});

单元测试

'use strict';

describe('chatEditor', () => {
  beforeEach(module('app', 'templates'));

  it('should add player', inject(($compile, $rootScope) => {
    $rootScope.onAddSpy = jasmine.createSpy('onAddSpy');
    const element = $compile('<chat-editor on-add="onAddSpy(message)"></chat-editor>')($rootScope);

    element.triggerHandler('click');

    $rootScope.$digest();

    expect($rootScope.onAddSpy).toHaveBeenCalledWith('test');
  }));
});

收到错误

  

使用[&#39; test&#39; ]但它从未被召唤过。

但如果我发表评论templateUrl并取消注释template,则测试成功通过。

我也安装并配置了karma-ng-html2js-preprocessor。我来自karma.conf.js

...

// list of files / patterns to load in the browser
files: [
  'app/**/*.module.js',
  'app/**/*.js',
  'app/**/*.html'
],

preprocessors: {
  'app/**/*.html': ['ng-html2js']
},

ngHtml2JsPreprocessor: {
  stripPrefix: 'app/',
  //prependPrefix: 'app/'
  moduleName: 'templates'
},
...

但它并没有解决问题。

1 个答案:

答案 0 :(得分:0)

经过很长一段时间我才明白这是什么问题。因为templateUrl是异步的,所以在单元测试期间不能同步加载模板,并且在编译阶段之后我们得到<chat-editor on-add="onAddSpy(message)"></chat-editor>元素而不是<chat-editor on-add="onAddSpy(message)"><div></div></chat-editor>

为了解决问题,可以使用几种方法。

1)将编译阶段移至beforeEach block

'use strict';

describe('chatEditor', () => {
  let element;

  beforeEach(module('app', 'templates'));

  beforeEach(inject(($compile, $rootScope) => {
    element = $compile('<chat-editor on-add="onAddSpy(message)"></chat-editor>')($rootScope);
    $rootScope.$digest();
  }));

  it('should add player', inject($rootScope => {
    $rootScope.onAddSpy = jasmine.createSpy('onAddSpy');

    element.triggerHandler('click');
    expect($rootScope.onAddSpy).toHaveBeenCalledWith('test');
  }));
});

2)使用$ timeout

'use strict';

describe('chatEditor', () => {
  beforeEach(module('app', 'templates'));

  it('should add player', inject(($compile, $rootScope, $timeout) => {
    $rootScope.onAddSpy = jasmine.createSpy('onAddSpy');

    const element = $compile('<chat-editor on-add="onAddSpy(message)"></chat-editor>')($rootScope);
    $rootScope.$digest();

    $timeout(() => {
      element.triggerHandler('click');
      expect($rootScope.onAddSpy).toHaveBeenCalledWith('test');
    });

    $timeout.flush();
  }));
});