Stubbing di un metodo di classe con Sinon.js


99

Sto cercando di bloccare un metodo usando sinon.js ma ottengo il seguente errore:

Uncaught TypeError: Attempted to wrap undefined property sample_pressure as function

Sono andato anche a questa domanda ( Stubbing e / o derisione di una classe in sinon.js? ) E ho copiato e incollato il codice ma ottengo lo stesso errore.

Ecco il mio codice:

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

Ecco jsFiddle ( http://jsfiddle.net/pebreo/wyg5f/5/ ) per il codice sopra e jsFiddle per la domanda SO che ho menzionato ( http://jsfiddle.net/pebreo/9mK5d/1/ ).

Mi sono assicurato di includere sinon nelle risorse esterne in jsFiddle e persino in jQuery 1.9. Che cosa sto facendo di sbagliato?

Risposte:


155

Il tuo codice sta tentando di bloccare una funzione Sensor, ma hai definito la funzione su Sensor.prototype.

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

è essenzialmente lo stesso di questo:

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

ma è abbastanza intelligente da vedere che Sensor["sample_pressure"]non esiste.

Quindi quello che vorresti fare è qualcosa del genere:

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

o

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

o

// Create a whole fake instance of 'Sensor' with none of the class's logic.
var sensor = sinon.createStubInstance(Sensor);
console.log(sensor.sample_pressure());

1
Quale cosa è deprecata?
loganfsmyth

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

Questo è nella mia risposta perché la domanda originale era espressamente posta al riguardo. Dato che la mia risposta non lo suggerisce come l'approccio corretto per cominciare, non sono sicuro di cosa mi stai chiedendo di cambiare. .returns(0)fa già la stessa cosa di .callFake(() => 0).
loganfsmyth

1
Non sembra che returnssia deprecato. sinonjs.org/releases/v3.0.0/stubs . @ danday74, fornire il riferimento.
allenhwkim

2
@ danday74 .stubcon una funzione come terzo argomento viene rimosso: github.com/sinonjs/sinon/blob/master/lib/sinon/stub.js#L17 Non c'è niente di sbagliato in .returnso .callsFake, quindi non c'è niente di sbagliato in questa risposta.
loganfsmyth

52

La risposta principale è deprecata. Ora dovresti usare:

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

O per metodi statici:

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

O per casi semplici usa solo resi:

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

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

O se vuoi stub un metodo per un'istanza:

const yourClassInstance = new YourClass();
sinon.stub(yourClassInstance, 'myMethod').returns({})

4
Sarebbe bello se potessi menzionare la versione specifica per il tuo suddetto metodo quando questo è stato aggiunto, ad sinonjsesempio callsFake(), per le versioni precedenti come può essere deprecato?
aitchkhan

3
Quando si utilizzano i moduli ES6: sto creando lo stub di YourClass.get () in un progetto di test. Il test chiama un altro modulo che importa YourClass. Il modulo YourClass.get () rispetterà lo stub? In caso contrario, esiste una soluzione?
Studente

1
Le tue soluzioni funzionano per me. Mi piacerebbe darti più punti: D Grazie.
Rubel Hasan

5

Mi sono imbattuto nello stesso errore cercando di deridere un metodo di una classe CoffeeScript usando Sinon.

Data una classe come questa:

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

Puoi sostituire il suo metodo con una spia in questo modo:

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

# ...

assert.ok(mySpy.called)

Basta sostituire spycon stubo mocksecondo necessità.

Nota che dovrai sostituire assert.okcon qualsiasi asserzione contenuta nel tuo framework di test.


2

Grazie a @loganfsmyth per il suggerimento. Sono stato in grado di far funzionare lo stub su un metodo di classe Ember come questo:

sinon.stub(Foo.prototype.constructor, 'find').returns([foo, foo]);
expect(Foo.find()).to.have.length(2)

3
Questo è un commento. Inizia con un ringraziamento a un'altra risposta e termina con una duplicazione del suo codice.
michelpm

5
Non sembra una duplicazione - qui c'è Foo.prototype.constructor, dove come nella risposta originale c'è Sensor.prototype. Poi di nuovo, Foo.prototype.constructornon funziona per me. :)
shaunc
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.