AngularJS:spyOn $ timeout和$ timeout.cancel

时间:2014-04-09 08:39:37

标签: angularjs timeout jasmine

测试使用Jasmine的$timeout方法时同时使用$timeout.cancelspyOn的AngularJS应用程序的一部分。

describe('<whatever>', function() {

  beforeEach(function() {
    spyOn(this, '$timeout').andCallThrough();
    spyOn(this.$timeout, 'cancel').andCallThrough();
    this.createController();
  });

  it('should <whatever>', function() {
    expect(this.$timeout).toHaveBeenCalled();
    expect(this.$timeout.cancel).toHaveBeenCalled();
  });

});

您的应用程序代码中应该遇到以下错误,该错误正在使用您的测试注入的内容。

TypeError: 'undefined' is not a function (evaluating '$timeout.cancel(timeoutPromise)');

2 个答案:

答案 0 :(得分:3)

如果您要在测试套件中运行console.log(Object.keys(this.$timeout));,您将看到以下输出;

LOG: ['identity', 'isSpy', 'plan', 'mostRecentCall', 'argsForCall', 'calls', 'andCallThrough', 'andReturn', 'andThrow', 'andCallFake', 'reset', 'wasCalled', 'callCount', 'baseObj', 'methodName', 'originalValue']

$timeout是一个AngularJS也在进行装饰的函数 - 因为函数是对象 - 使用cancel方法。因为这不是常见的事情,所以Jasmine取代而不是使用它的间谍实施来增强$timeout - 破坏$timeout.cancel

解决这个问题的方法是在cancel间谍被Jasmine的$timeout间谍覆盖后再次让$timeout间谍回来,如下所示;

describe('<whatever>', function() {

  beforeEach(function() {
    spyOn(this.$timeout, 'cancel').andCallThrough();
    var $timeout_cancel = this.$timeout.cancel;
    spyOn(this, '$timeout').andCallThrough();
    this.$timeout.cancel = $timeout_cancel;
    this.createController();
  });

  it('should <whatever>', function() {
    expect(this.$timeout).toHaveBeenCalled();
    expect(this.$timeout.cancel).toHaveBeenCalled();
  });

});

答案 1 :(得分:0)

这对我来说只需要$ interval,所以它应该可以用于$ timeout。 (茉莉花2)

var $intervalSpy = jasmine.createSpy('$interval', $interval).and.callThrough();

然后我可以做到两件事:

expect($intervalSpy.cancel).toHaveBeenCalledTimes(1);
expect($intervalSpy).toHaveBeenCalledTimes(1);