0

当测试一个主干模型的事件已经被 sinon spy 触发时,它错误地错误: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);
});

我知道要修复,您必须像const spy = sinon.spy(Model.prototype, 'doSomething');new Model()调用之前的行中一样将 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);
});

好奇为什么它需要在第一个实例中放置在模型的原型上,但在第二个实例上工作?

4

1 回答 1

1

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();
});

它可以工作,因为它没有引用原始方法,方法调用是动态的

于 2017-05-17T12:57:08.563 回答