在使用 Karma 和 Sinon 时,我如何能够测试绑定到事件总线的 Backbone 模型的方法是否已触发?
How am I able to test that a Backbone model's method bound to the event bus has fired when using Karma and Sinon?
当测试 backbone 模型的事件已用 sinon 间谍触发时,它错误地出错:expected doSomething to be called once but was called 0 times
,即使它似乎是在将控制台日志放入方法主体时执行的。测试函数如下所示:
it('Y U NO WORK', function() {
const events = {};
_.extend(events, Backbone.Events);
const Model = Backbone.Model.extend({
initialize: function() {
this.listenTo(events, 'doSomething', this.doSomething);
},
doSomething: function() {},
});
const model = new Model();
const spy = sinon.spy(model, 'doSomething');
events.trigger('doSomething');
sinon.assert.calledOnce(spy);
});
我知道要解决这个问题,您必须在 new Model()
调用之前的行中像 const spy = sinon.spy(Model.prototype, 'doSomething');
一样将 sinon spy 放在模型的原型上,但是它似乎可以正常工作放入模型实例,如下所示:
it('And this does work', function() {
const Model = Backbone.Model.extend();
const model = new Model();
const spy = sinon.spy(model, 'set');
model.set('foo', 'bar');
sinon.assert.calledOnce(spy);
});
想知道为什么它需要在第一个实例中放在模型的原型上,但在第二个实例中却适用于模型实例?
Spy 将原始方法替换为自定义方法,以了解何时调用它(它保留对原始方法的引用以便稍后恢复)。所以在第一种情况下,你在创建间谍之前设置了一个事件监听器。事件系统实际上直接引用原始方法,而不是间谍。 Spy 对此无能为力,Spy 不知道它何时被调用。
在设置事件侦听器之前需要先设置间谍,例如:
it('Y U NO WORK', function() {
var spy;
const events = {};
_.extend(events, Backbone.Events);
const Model = Backbone.Model.extend({
initialize: function() {
spy = sinon.spy(this, 'doSomething');
this.listenTo(events, 'doSomething', this.doSomething);
//now same as this.listenTo(events, 'doSomething', spy);
},
doSomething: function() {},
});
const model = new Model();
events.trigger('doSomething');
sinon.assert.calledOnce(spy);
});
或者避免直接引用原始方法,例如:
this.listenTo(events, 'doSomething', function() {
//by the time this is invoked, original has been replaced with spy
this.doSomething();
});
它会起作用,因为它没有保留对原始方法的引用,方法调用是动态的
当测试 backbone 模型的事件已用 sinon 间谍触发时,它错误地出错:expected doSomething to be called once but was called 0 times
,即使它似乎是在将控制台日志放入方法主体时执行的。测试函数如下所示:
it('Y U NO WORK', function() {
const events = {};
_.extend(events, Backbone.Events);
const Model = Backbone.Model.extend({
initialize: function() {
this.listenTo(events, 'doSomething', this.doSomething);
},
doSomething: function() {},
});
const model = new Model();
const spy = sinon.spy(model, 'doSomething');
events.trigger('doSomething');
sinon.assert.calledOnce(spy);
});
我知道要解决这个问题,您必须在 new Model()
调用之前的行中像 const spy = sinon.spy(Model.prototype, 'doSomething');
一样将 sinon spy 放在模型的原型上,但是它似乎可以正常工作放入模型实例,如下所示:
it('And this does work', function() {
const Model = Backbone.Model.extend();
const model = new Model();
const spy = sinon.spy(model, 'set');
model.set('foo', 'bar');
sinon.assert.calledOnce(spy);
});
想知道为什么它需要在第一个实例中放在模型的原型上,但在第二个实例中却适用于模型实例?
Spy 将原始方法替换为自定义方法,以了解何时调用它(它保留对原始方法的引用以便稍后恢复)。所以在第一种情况下,你在创建间谍之前设置了一个事件监听器。事件系统实际上直接引用原始方法,而不是间谍。 Spy 对此无能为力,Spy 不知道它何时被调用。
在设置事件侦听器之前需要先设置间谍,例如:
it('Y U NO WORK', function() {
var spy;
const events = {};
_.extend(events, Backbone.Events);
const Model = Backbone.Model.extend({
initialize: function() {
spy = sinon.spy(this, 'doSomething');
this.listenTo(events, 'doSomething', this.doSomething);
//now same as this.listenTo(events, 'doSomething', spy);
},
doSomething: function() {},
});
const model = new Model();
events.trigger('doSomething');
sinon.assert.calledOnce(spy);
});
或者避免直接引用原始方法,例如:
this.listenTo(events, 'doSomething', function() {
//by the time this is invoked, original has been replaced with spy
this.doSomething();
});
它会起作用,因为它没有保留对原始方法的引用,方法调用是动态的