使用Jasmine监视构造函数

时间:2012-02-19 07:54:08

标签: javascript jasmine spy

我正在使用Jasmine来测试是否创建了某些对象并调用了它们的方法。

我有一个jQuery小部件,它创建flipcounter对象并调用它们的setValue方法。 flipcounter的代码在这里:https://bitbucket.org/cnanney/apple-style-flip-counter/src/13fd00129a41/js/flipcounter.js

flipcounters使用:

创建
var myFlipCounter = new flipCounter("counter", {inc: 23, pace: 500});

我想测试创建flipcounters并调用setValue方法。我的问题是如何在创建这些对象之前监视这些对象?我是否会监视构造函数并返回虚假对象?示例代码确实会有所帮助。谢谢你的帮助! :)

更新

我试图像这样在flipCounter上进行间谍活动:

myStub = jasmine.createSpy('myStub');
spyOn(window, 'flipCounter').andReturn(myStub);

//expectation
expect(window.flipCounter).toHaveBeenCalled();

然后通过flipCounter测试setValue调用:

spyOn(myStub, 'setValue');

//expectation
expect(myStub.setValue).toHaveBeenCalled();

初始化flipCounter的第一个测试很好,但是为了测试setValue调用,我得到的所有内容都不存在' setValue()方法不存在'错误。我这样做是对的吗?谢谢!

6 个答案:

答案 0 :(得分:41)

flipCounter只是另一个函数,即使它也恰好构造了一个对象。因此你可以这样做:

var cSpy = spyOn(window, 'flipCounter');

获取间谍,并对其进行各种检查或说:

var cSpy = spyOn(window, 'flipCounter').andCallThrough();
var counter = flipCounter('foo', options);
expect(cSpy).wasCalled();

然而,这似乎有点矫枉过正。这样就足够了:

var myFlipCounter = new flipCounter("counter", options);
expect(myFlipCounter).toBeDefined();
expect(myFlipCounter.getValue(foo)).toEqual(bar);

答案 1 :(得分:10)

当你想要模拟具有需要监视的属性的对象时,我建议使用jasmine.createSpyObj()

myStub = jasmine.createSpyObj('myStub', ['setValue']);
spyOn(window, 'flipCounter').andReturn(myStub);

这会测试与预期flipCounter接口的互动,而不依赖于flipCounter实现。

答案 2 :(得分:4)

您必须为flipCounter实现一个假构造函数,将setValue属性设置为间谍函数。让我们说你要测试的功能就是:

function flipIt() {
  var myFlipCounter = new flipCounter("counter", {inc: 23, pace: 500});
  myFlipCounter.setValue(100);
}

您的规范应如下所示:

describe('flipIt', function () {
  var setValue;
  beforeEach(function () {
    setValue = jasmine.createSpy('setValue');
    spyOn(window, 'flipCounter').and.callFake(function () {
      this.setValue = setValue;
    });
    flipIt();
  });
  it('should call flipCounter constructor', function () {
    expect(window.flipCounter)
      .toHaveBeenCalledWith("counter", {inc: 23, pace: 500});
  });
  it('should call flipCounter.setValue', function () {
    expect(setValue).toHaveBeenCalledWith(100);
  });
});

答案 3 :(得分:3)

以下不依赖于“窗口”。让我们说这是你要测试的代码 -

function startCountingFlips(flipCounter) {
    var myFlipCounter = new flipCounter("counter", {inc: 23, pace: 500});
}

您的测试可能是 -

var initSpy = jasmine.createSpy('initFlipCounter');
var flipCounter = function(id, options) {
    initSpy(id, options);
}
startCountingFlips(flipCounter);
expect(initSpy).toHaveBeenCalledWith("counter", {inc:23, pace:500});

答案 4 :(得分:1)

我测试构造函数的版本是监视原型:

spyOn(flipCounter.prototype, 'setValue').and.callThrough();
var myFlipCounter = new flipCounter("counter", {inc: 23, pace: 500});
expect(flipCounter.prototype.setValue).toHaveBeenCalledTimes(1);

答案 5 :(得分:-3)

不知道如何使用茉莉花模拟做到这一点,但如果你想要强大的模拟/间谍/存根,我推荐sinon.js,这对茉莉花很有用。

来自docs:

  

测试间谍是一个记录参数,返回值,的函数   所有调用的抛出值和异常值(如果有的话)。一个测试   spy可以是匿名函数,也可以包装现有函数。

     模仿(和模拟期望)是虚假的方法(如间谍)   预编程行为(如存根)以及预编程   期望。如果没有使用,模拟将无法通过测试   预期

使用sinon.js你可以创建一个flipCounter构造函数的模拟器,它返回另一个间谍。

然后断言使用constructorMock.calledWithNew()调用构造函数,并声明返回的spy是使用returnedSpy.calledWith(arg1,arg2 ...)调用的。