Jasmine - 在构造函数中监视方法调用

Lev*_*lum 61 javascript testing spy jasmine

我想测试在我的Javascript对象构造函数中是否调用以下方法.从我在Jasmine文档中看到的,我可以窥探一个构造函数方法,并且我可以在实例化对象之后监视方法,但是在构造对象之前我似乎无法监视方法.

物体:

Klass = function() {
    this.called_method();
};

Klass.prototype.called_method = function() {
  //method to be called in the constructor.
}
Run Code Online (Sandbox Code Playgroud)

我想在规范中做这样的事情:

it('should spy on a method call within the constructor', function() {
    spyOn(window, 'Klass');
    var obj = new Klass();
    expect(window.Klass.called_method).toHaveBeenCalled();
});
Run Code Online (Sandbox Code Playgroud)

Dav*_*ton 105

直接间谍原型方法:

describe("The Klass constructor", function() {
  it("should call its prototype's called_method", function() {
      spyOn(Klass.prototype, 'called_method');  //.andCallThrough();
      var k = new Klass();
      expect(Klass.prototype.called_method).toHaveBeenCalled();
  });
});
Run Code Online (Sandbox Code Playgroud)

  • 这次真是万分感谢.最好的描述我整天都看过这个主题 (3认同)
  • 规范完成后,Jasmine 1.3.1+完全恢复功能,因此副作用不再是问题,不再需要重置方法.好极了!供参考:https://github.com/jasmine/jasmine/issues/236 (2认同)

ale*_*mce 12

从广义上讲,我同意Dave Newton在上面的回答.但是,您应该考虑这种方法的一些边缘情况.

使用另一个测试用例来改变Dave的解决方案:

// production code
var Klass = function() {
  this.call_count = 0;
  this.called_method();
};
Klass.prototype.called_method = function() {
  ++this.call_count;
};

// test code
describe("The Klass constructor", function() {
  it("should call its prototype's called_method", function() {
    spyOn(Klass.prototype, 'called_method');
    var k = new Klass();
    expect(k.called_method).toHaveBeenCalled();
  });
  it('some other test', function() {
    var k = new Klass();
    expect(k.call_count).toEqual(1);
  });
});
Run Code Online (Sandbox Code Playgroud)

第二次测试将失败,因为第一次测试中的间谍设置​​在测试边界内持续存在于第二种方法中; called_method不会增加call_count,所以this.call_count不等于1.也可能出现误报的情景 - 通过的测试,不应该.

除此之外,因为间谍仍然存在,所创建的Klass实例越多,间谍将消耗的内存堆就越大,因为间谍会记录每次调用called_method.在大多数情况下这可能不是问题,但你应该注意它,以防万一.

解决这个问题的一个简单方法是确保间谍在使用后被移除.它可能看起来有点难看,但这样的工作:

// test code
describe("The Klass constructor", function() {
  it("should call its prototype's called_method", function() {
    var spy = jasmine.createSpy('called_method');
    var method = Klass.prototype.called_method;
    Klass.prototype.called_method = spy;
    var k = new Klass();
    expect(spy).toHaveBeenCalled();
    Klass.prototype.called_method = method;
  });
Run Code Online (Sandbox Code Playgroud)

[注意 - 完成一点意见]更好的解决方案是改变编写生产代码的方式,使代码更容易测试.作为一项规则,监视原型可能是一种需要避免的代码气味.而不是在构造函数中实例化依赖项,而是注入它们.而不是在构造函数中进行初始化,而是遵循适当的init方法.