Stubbing une méthode de classe avec Sinon.js

99

J'essaie de stuber une méthode en utilisant sinon.js mais j'obtiens l'erreur suivante:

Uncaught TypeError: Attempted to wrap undefined property sample_pressure as function

Je suis également allé à cette question ( Stubbing et / ou moqueur d'une classe dans sinon.js? ) Et copié et collé le code mais j'obtiens la même erreur.

Voici mon code:

Sensor = (function() {
  // A simple Sensor class

  // Constructor
  function Sensor(pressure) {
    this.pressure = pressure;
  }

  Sensor.prototype.sample_pressure = function() {
    return this.pressure;
  };

  return Sensor;

})();

// Doesn't work
var stub_sens = sinon.stub(Sensor, "sample_pressure").returns(0);

// Doesn't work
var stub_sens = sinon.stub(Sensor, "sample_pressure", function() {return 0});

// Never gets this far
console.log(stub_sens.sample_pressure());

Voici le jsFiddle ( http://jsfiddle.net/pebreo/wyg5f/5/ ) pour le code ci-dessus, et le jsFiddle pour la question SO que j'ai mentionnée ( http://jsfiddle.net/pebreo/9mK5d/1/ ).

Je me suis assuré d'inclure sinon dans les ressources externes de jsFiddle et même de jQuery 1.9. Qu'est-ce que je fais mal?

Paul
la source

Réponses:

155

Votre code tente de stuber une fonction sur Sensor, mais vous avez défini la fonction sur Sensor.prototype.

sinon.stub(Sensor, "sample_pressure", function() {return 0})

est essentiellement le même que celui-ci:

Sensor["sample_pressure"] = function() {return 0};

mais c'est assez intelligent pour voir que cela Sensor["sample_pressure"]n'existe pas.

Donc, ce que vous voudriez faire est quelque chose comme ceci:

// Stub the prototype's function so that there is a spy on any new instance
// of Sensor that is created. Kind of overkill.
sinon.stub(Sensor.prototype, "sample_pressure").returns(0);

var sensor = new Sensor();
console.log(sensor.sample_pressure());

ou

// Stub the function on a single instance of 'Sensor'.
var sensor = new Sensor();
sinon.stub(sensor, "sample_pressure").returns(0);

console.log(sensor.sample_pressure());

ou

// Create a whole fake instance of 'Sensor' with none of the class's logic.
var sensor = sinon.createStubInstance(Sensor);
console.log(sensor.sample_pressure());
loganfsmyth
la source
1
Quelle chose est obsolète?
loganfsmyth
sinon.stub (Sensor, "sample_pressure", function () {return 0})
danday74
C'est dans ma réponse parce que la question initiale portait spécifiquement à ce sujet. Étant donné que ma réponse ne le suggère pas comme la bonne approche pour commencer, je ne suis pas sûr de ce que vous me demandez de changer. .returns(0)fait déjà la même chose que .callFake(() => 0).
loganfsmyth
1
Cela ne semble pas returnsobsolète. sinonjs.org/releases/v3.0.0/stubs . @ danday74, veuillez fournir la référence.
allenhwkim
2
@ danday74 .stubavec une fonction comme troisième argument est supprimé: github.com/sinonjs/sinon/blob/master/lib/sinon/stub.js#L17 Il n'y a rien de mal avec .returnsou .callsFake, donc il n'y a rien de mal avec cette réponse.
loganfsmyth
52

La réponse principale est obsolète. Vous devez maintenant utiliser:

sinon.stub(YourClass.prototype, 'myMethod').callsFake(() => {
    return {}
})

Ou pour les méthodes statiques:

sinon.stub(YourClass, 'myStaticMethod').callsFake(() => {
    return {}
})

Ou pour les cas simples, utilisez simplement les retours:

sinon.stub(YourClass.prototype, 'myMethod').returns({})

sinon.stub(YourClass, 'myStaticMethod').returns({})

Ou si vous souhaitez stuber une méthode pour une instance:

const yourClassInstance = new YourClass();
sinon.stub(yourClassInstance, 'myMethod').returns({})
danday74
la source
4
Ce serait génial si vous pouviez mentionner la version spécifique de votre méthode lorsque cela a été ajouté, sinonjsc'est- à- dire de callsFake()plus, pour les versions plus anciennes, comment cela peut-il être désapprouvé?
aitchkhan
3
Lors de l'utilisation de modules ES6: je crée le stub de YourClass.get () dans un projet de test. Le test appelle un autre module qui importe YourClass. Le module YourClass.get () respectera-t-il le stub? Sinon, y a-t-il une solution?
Apprenant le
1
Vos solutions fonctionnent pour moi. Je souhaite si je vous donne plus de points: D Merci.
Rubel hasan le
5

J'ai rencontré la même erreur en essayant de simuler une méthode d'une classe CoffeeScript utilisant Sinon.

Étant donné une classe comme celle-ci:

class MyClass
  myMethod: ->
    # do stuff ...

Vous pouvez remplacer sa méthode par un espion de cette façon:

mySpy = sinon.spy(MyClass.prototype, "myMethod")

# ...

assert.ok(mySpy.called)

Remplacez simplement spypar stubou mockau besoin.

Notez que vous devrez remplacer assert.okpar n'importe quelle assertion de votre framework de test.

Nathan Arthur
la source
2

Merci à @loganfsmyth pour le tuyau. J'ai pu faire fonctionner le stub sur une méthode de classe Ember comme celle-ci:

sinon.stub(Foo.prototype.constructor, 'find').returns([foo, foo]);
expect(Foo.find()).to.have.length(2)
Scott Nedderman
la source
3
Ceci est un commentaire. Commence par un merci à une autre réponse et se termine par une duplication de son code.
michelpm
5
Cela ne ressemble pas à une duplication - ici il y a Foo.prototype.constructor, là où comme dans la réponse originale il y a Sensor.prototype. Là encore, Foo.prototype.constructorça ne marche pas pour moi. :)
shaunc