0

Lors d'un test de déclenchement d'un événement de modèle de backbone avec un espion tiers, il commet des erreurs erronées: expected doSomething to be called once but was called 0 times, même s'il semble s'exécuter lorsqu'un journal de console est placé dans le corps de la méthode. La fonction de test ressemble à:Comment puis-je tester si la méthode d'un modèle Backbone lié au bus d'événements a été déclenchée lors de l'utilisation de Karma et Sinon?

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

Je sais que pour fixer, vous auriez à mettre l'espion sinon sur le prototype du modèle comme const spy = sinon.spy(Model.prototype, 'doSomething'); dans la ligne avant que l'appel new Model(), mais il semble fonctionner sans problème lorsque mettre dans l'instance de modèle, comme ci-dessous:

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

curieux de savoir pourquoi il a besoin d'être mis sur le prototype en première instance du modèle, mais fonctionne sur l'instance de modèle dans la seconde?

Répondre

1

Espion de remplace la méthode d'origine par une méthode personnalisée pour savoir quand elle est invoquée (elle contient la référence à l'original pour la restauration ultérieure). Ainsi, dans le premier cas, vous avez configuré un écouteur d'événement avant de créer l'espion. Le système d'événements tient en fait une référence directe à la méthode originale, pas à l'espion. Spy ne peut rien y faire, Spy ne sait pas quand il est invoqué.

Vous devez configurer l'espion avant de mettre en place l'écouteur d'événement, quelque chose comme:

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

Ou éviter de garder des références directes à la méthode originale comme:

this.listenTo(events, 'doSomething', function() { 
    //by the time this is invoked, original has been replaced with spy 
    this.doSomething(); 
}); 

Itd travail car il ne contient pas de référence à la méthode d'origine, l'invocation de la méthode est dynamique