Stubbing Backbone listenTo与sinon的回调

时间:2014-05-23 07:58:32

标签: javascript testing backbone.js sinon

我试图通过存根Backbone.View的listenTo回调方法来实现一个简单的测试。

但是,我似乎无法直接执行此操作 - 我必须将回调包装在匿名函数中。知道为什么会发生这种情况,我怎么能避免使用包装器并仍然能够存回回调?

这不起作用:

// MyView.js

var MyView = Backbone.View.Extend({

  initialize: function() {
    this.listenTo('some:event', this.myFunc);
  },

  myFunc: function() {
    //.. do useful stuff
  }

});

// Trying to stub with sinon

var view = new MyView();
sinon.stub( view, 'myFunc' );

view.trigger('some:event');

view.myFunc.called; // is false;

然而,这有效:

// MyView.js

var MyView = Backbone.View.Extend({

  initialize: function() {
    this.listenTo('some:event', function() { this.myFunc });
  },

  myFunc: function() {
    //.. do useful stuff
  }

});

// Trying to stub with sinon

var view = new MyView();
sinon.stub( view, 'myFunc' );

view.trigger('some:event');

view.myFunc.called; // is true;

1 个答案:

答案 0 :(得分:4)

您可以在创建视图的原型之前将其存根:

sinon.stub(MyView.prototype, 'myFunc');
var view = new MyView();
view.trigger('some:event');

view.myFunc.called; // is true;

Sinon还有Util function名为createStubInstance。但是,我从未尝试过,所以我不知道它有多好用;

sinon.createStubInstance(MyView);

编辑以解决评论(以相当松散的术语):

由于prototypal inheritance works的方式以及JS通过引用传递函数的方式。首次创建视图的实例时,myFunc指向MyView.prototype.myFunc的引用。这意味着当调用initialize函数时,listenTo事件处理程序已设置,并且它正在使用当时对myFunc的引用。

创建视图后对myFunc函数进行存根只会更改view.myFunc指向的引用(它将更改为新的存根函数引用而不是MyView.prototype.myFunc引用)。但这不会改变listenTo使用的引用。

解决问题的一种方法是做你做的事情:

this.listenTo('some:event', function() { this.myFunc() });

这解决了问题,方法是将listenTo指向一个匿名函数,该函数在事件触发器上运行时,将在调用时从视图中评估myFunc,这将是存根参考。

解决此问题的另一种方法是对原型函数进行存根,因此在创建实例时,myFunc使用的listenTo引用是存根函数。

希望这有帮助。