一尘不染

使用Karma和Angular的Jasmine模拟链接方法

angularjs

我想嘲笑angular.element。我想确保angular.element已经被调用了一定的次数,并且也anguler.element.attr已经被调用了。

我有以下代码:

var things = $scope.getThings();

for (var i = 0; i < things.length; i++) {
  if (things[i].type == "xyz") {
    angular.element("#thing-" + things[i].id)
      .attr("foo", things[i].bar);
  };
};

在我的测试中,我有:

var things = [
  {
    id: 1,
    type: "xyz",
    bar: 10
  },
  {
    id: 2,
    type: "abc",
    bar: 33
  }
];

spyOn($rootScope, "getThings").and.returnValue(things);
spyOn(angular, "element").and.returnValue();

$rootScope.doThings(); // call controller method

expect(angular.element.calls.count()).toBe(1);

但是它给出了以下错误:

TypeError:未定义不是对象(评估’angular.element(“#thing-” + Things [i] .id).attr’)

我还希望我的测试具有以下内容:

expect(angular.element.attr.calls.count()).toBe(1);
expect(angular.element.attr).tohaveBeenCalledWith("foo", things[0].bar);

阅读 252

收藏
2020-07-04

共1个答案

一尘不染

监视或模拟链接方法的方式仅取决于如何在被监视对象上定义它们。

在Angular
jqLit​​e的情况下,或者在您的情况下,jQuery(都是通过angular.element立面透明地提供服务)的链接方法是在构造函数原型上定义的,该方法在工厂函数中显示为angular.element.prototypeor
jQuery.prototype(或angular.element === jQuery在加载jQuery时)。

为了监视两者angular.elementangular.element(...).attr应该是:

spyOn(angular, 'element').and.callThrough();
spyOn(angular.element.prototype, 'attr').and.callThrough();
...
expect(angular.element).toHaveBeenCalled();
expect(angular.element.prototype.attr).toHaveBeenCalled();

callThrough 在这种情况下非常重要,因为否则整个链都应该手动存根。

2020-07-04