Jasmine模拟Karma和Angular的链式方法

Jasmine mock chained methods with Karma and Angular

本文关键字:方法 Angular 模拟 Karma Jasmine      更新时间:2023-09-26

我想模拟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:undefined不是对象(正在评估'angular.element("#thing-"+things[i].id).attr')

我还希望我的测试有这样的东西:

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

监视或模拟链式方法的方式完全取决于它们在监视对象上的定义方式。

在Angular jqLite的情况下,或者在您的情况下:jQuery(两者都通过angular.element facade透明地提供服务)在构造函数原型上定义了链式方法,该方法在工厂函数上公开为angular.element.prototypejQuery.prototype(加载jQuery时为angular.element === 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在这种情况下很重要,因为否则整个链都应该手动断开。

尝试添加以下代码:

var spy;
beforeEach(function() {
    spy = spyOn(angular, 'element').....
});
afterEach(function() {
    spy.andCallThrough();
});

您可以在以下位置找到更多信息:Jasmin docs