【问题标题】:Angular: How to spy on $element.onAngular:如何监视 $element.on
【发布时间】:2016-02-17 18:14:50
【问题描述】:

我有一个指令在其link 函数中执行类似的操作

angular.module('myApp')
    .directive('barFoo', function() {
        return {
            restrict: 'E',
            link: function (scope, element) {
                element.on('click', ....);
            }
        };
    });

现在我想在我的单元测试中验证它是否正确调用on

element = angular.element('<bar-foo></bar-foo>');
$compile(element)(scope);
spyOn(element, 'on');
...
expect(element.on).toHaveBeenCalled();

它告诉我间谍没有被调用。从我在网上找到的内容来看,angular/jquery 每次都会围绕 DOM 元素创建一个新的包装器。这意味着我的指令中的element 与我的规范文件中的元素不同。最有可能(未验证)element[0] 可能是相同的。我还试图监视angular.element

var mockEl = { on: angular.noop };
spyOn(angular, 'element').andReturn(mockEl);
spyOn(mockEl, 'on');

但这似乎比它修复的要多(例如,我还需要像 isloateScope 这样的函数)。

无论如何,有没有一些简单的方法可以监视指令中使用的元素的on 函数?

【问题讨论】:

  • 为什么首先要测试它?点击事件(以及其他 DOM)必须在 e2e 中进行测试,而本规范以不足的方式重复了这一点。
  • 好点,但如果有人不太了解组件,在重构期间将其删除怎么办。或者基于某些逻辑(将其包装在 if 语句中),测试绑定是否发生可能很有用,对吧?

标签: javascript angularjs unit-testing angularjs-directive jasmine


【解决方案1】:

链接功能可以单独测试

element = angular.element('<bar-foo');
spyOn(element, 'on');
BarFooDirective[0].link(scope, element);
expect(element.on).toHaveBeenCalled();

如果它足够简单(远离 attrs、必需的控制器、依赖项),否则规范将导致比它所能解决的更多的问题。

否则可以测试like it is done by the framework:

element = angular.element('<bar-foo');
expect(angular.element._data(element[0]).events.click).toBeDefined();

对于可能在自身或子指令中定义多个click 侦听器的实际指令,仅确保存在侦听器是不够的。通常你可能想封装内部函数,但匿名点击处理程序也可以暴露在作用域中进行测试:

element = angular.element('<bar-foo');
expect(angular.element._data(element[0]).events.click).toContain(scope.onClick);

【讨论】:

    【解决方案2】:

    好吧,没有必要测试on 方法。您可以在triggerHandler() 的帮助下测试事件绑定

    link: function (scope, element) {
        element.on('click', 'something to heppen');
    }
    

    测试:

    element = angular.element('<bar-foo></bar-foo>');
    $compile(element)(scope); 
    $(element[0]).triggerHandler('click');
    expect('something binded to click event to happen');
    

    【讨论】:

    • 我不是在测试on 方法是否有效,而是在测试它是否被调用以及是否传递了正确的参数。你的建议听起来很中肯!
    【解决方案3】:

    如果你已经像这样在 beforeEach 中编译了你的元素:

    myEl = '<div my-el>MY EL</div>';
    scope = $rootScope.$new();
    directiveElement = $compile(myEl)(scope);
    scope.$digest();
    

    尝试将mousedown 替换为您正在测试的事件,如下所示:

    expect(directiveElement.on.mousedown).toBeDefined;
    

    【讨论】:

      猜你喜欢
      • 2013-11-07
      • 2022-09-30
      • 2018-08-12
      • 1970-01-01
      • 2014-09-10
      • 2018-05-10
      • 2015-03-15
      • 2017-10-20
      • 1970-01-01
      相关资源
      最近更新 更多