Stubben einer Klassenmethode mit Sinon.js

99

Ich versuche, eine Methode mit sinon.js zu stubben, erhalte jedoch den folgenden Fehler:

Uncaught TypeError: Attempted to wrap undefined property sample_pressure as function

Ich ging auch zu dieser Frage ( Stubben und / oder Verspotten einer Klasse in sinon.js? ) Und kopierte und fügte den Code ein, aber ich erhalte den gleichen Fehler.

Hier ist mein 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());

Hier ist die jsFiddle ( http://jsfiddle.net/pebreo/wyg5f/5/ ) für den obigen Code und die jsFiddle für die SO-Frage, die ich erwähnt habe ( http://jsfiddle.net/pebreo/9mK5d/1/). ).

Ich habe dafür gesorgt, dass sinon in die externen Ressourcen in jsFiddle und sogar in jQuery 1.9 aufgenommen wird. Was mache ich falsch?

Paul
quelle

Antworten:

155

Ihr Code versucht, eine Funktion zu stubben Sensor, aber Sie haben die Funktion aktiviert Sensor.prototype.

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

ist im Wesentlichen das gleiche wie das:

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

aber es ist klug genug zu sehen, dass es Sensor["sample_pressure"]das nicht gibt.

Was Sie also tun möchten, ist Folgendes:

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

oder

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

oder

// 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
quelle
1
Welches Ding ist veraltet?
Loganfsmyth
sinon.stub (Sensor, "sample_pressure", function () {return 0})
danday74
Das ist in meiner Antwort, weil die ursprüngliche Frage speziell danach gestellt wurde. Da meine Antwort dies zunächst nicht als den richtigen Ansatz vorschlägt, bin ich mir nicht sicher, was Sie von mir verlangen, zu ändern. .returns(0)macht schon das gleiche wie .callFake(() => 0).
Loganfsmyth
1
Es scheint nicht returnsveraltet zu sein. sinonjs.org/releases/v3.0.0/stubs . @ danday74, bitte geben Sie die Referenz an.
Allenhwkim
2
@ danday74 .stubmit einer Funktion als drittes Argument wird entfernt: github.com/sinonjs/sinon/blob/master/lib/sinon/stub.js#L17 An.returns oder ist nichts falsch mit oder .callsFake, also ist an dieser Antwort nichts falsch.
Loganfsmyth
52

Die Top-Antwort ist veraltet. Sie sollten jetzt verwenden:

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

Oder für statische Methoden:

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

Oder verwenden Sie für einfache Fälle einfach die Rückgabe:

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

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

Oder wenn Sie eine Methode für eine Instanz stubben möchten:

const yourClassInstance = new YourClass();
sinon.stub(yourClassInstance, 'myMethod').returns({})
danday74
quelle
4
Es wäre großartig, wenn Sie die spezifische Version für Ihre Methode erwähnen könnten, wenn diese hinzugefügt wurde, sinonjsdh callsFake()darüber hinaus, für die älteren Versionen, wie kann dies veraltet sein?
Aitchkhan
3
Bei Verwendung von ES6-Modulen: Ich erstelle den Stub von YourClass.get () in einem Testprojekt. Der Test ruft ein anderes Modul auf, das YourClass importiert. Wird das Modul YourClass.get () den Stub respektieren? Wenn nicht, gibt es eine Lösung?
Lerner
1
Ihre Lösungen funktionieren für mich. Ich wünschte, ich gebe Ihnen mehr Punkte: D Danke.
Rubel Hasan
5

Ich bin auf denselben Fehler gestoßen, als ich versucht habe, eine Methode einer CoffeeScript-Klasse mit Sinon zu verspotten.

Bei einer Klasse wie dieser:

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

Sie können die Methode folgendermaßen durch einen Spion ersetzen:

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

# ...

assert.ok(mySpy.called)

Ersetzen Sie einfach spymit stuboder mocknach Bedarf.

Beachten Sie, dass Sie durch die assert.okBehauptung Ihres Testframeworks ersetzen müssen .

Nathan Arthur
quelle
2

Danke an @loganfsmyth für den Tipp. Ich konnte den Stub dazu bringen, an einer Ember-Klassenmethode wie dieser zu arbeiten:

sinon.stub(Foo.prototype.constructor, 'find').returns([foo, foo]);
expect(Foo.find()).to.have.length(2)
Scott Nedderman
quelle
3
Dies ist ein Kommentar. Beginnt mit einem Dank an eine andere Antwort und endet mit einer Vervielfältigung des Codes.
Michelpm
5
Sieht nicht nach einer Vervielfältigung aus - hier gibt es Foo.prototype.constructor, wo wie in der ursprünglichen Antwort Sensor.prototype. Andererseits Foo.prototype.constructorfunktioniert das bei mir nicht. :)
Shaunc