Apuntando un método de clase con Sinon.js

99

Estoy tratando de apuntar un método usando sinon.js pero obtengo el siguiente error:

Uncaught TypeError: Attempted to wrap undefined property sample_pressure as function

También fui a esta pregunta (¿ Stubbing y / o burlarse de una clase en sinon.js? ) Y copié y pegué el código, pero obtengo el mismo error.

Aquí está mi código:

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

Aquí está el jsFiddle ( http://jsfiddle.net/pebreo/wyg5f/5/ ) para el código anterior y el jsFiddle para la pregunta SO que mencioné ( http://jsfiddle.net/pebreo/9mK5d/1/ ).

Me aseguré de incluir sinon en los recursos externos en jsFiddle e incluso en jQuery 1.9. ¿Qué estoy haciendo mal?

Pablo
fuente

Respuestas:

155

Su código está intentando bloquear una función Sensor, pero ha definido la función en Sensor.prototype.

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

es esencialmente lo mismo que esto:

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

pero es lo suficientemente inteligente para ver eso Sensor["sample_pressure"] no existe.

Entonces, lo que querría hacer es algo como esto:

// 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());
loganfsmyth
fuente
1
¿Qué cosa está en desuso?
loganfsmyth
sinon.stub (Sensor, "sample_pressure", function () {return 0})
danday74
Eso está en mi respuesta porque la pregunta original preguntaba específicamente al respecto. Dado que mi respuesta no sugiere que sea el enfoque correcto para empezar, no estoy seguro de qué me está pidiendo que cambie. .returns(0)ya hace lo mismo que .callFake(() => 0).
loganfsmyth
1
No parece que returnsesté en desuso. sinonjs.org/releases/v3.0.0/stubs . @ danday74, proporcione la referencia.
allenhwkim
2
@ danday74 .stubcon una función cuando se elimina el tercer argumento: github.com/sinonjs/sinon/blob/master/lib/sinon/stub.js#L17 No hay nada de malo en .returnso .callsFake, por lo que no hay nada de malo en esta respuesta.
loganfsmyth
52

La respuesta principal está obsoleta. Ahora deberías usar:

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

O para métodos estáticos:

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

O para casos simples, use devoluciones:

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

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

O si desea apuntar un método para una instancia:

const yourClassInstance = new YourClass();
sinon.stub(yourClassInstance, 'myMethod').returns({})
danday74
fuente
4
Sería genial si pudiera mencionar la versión específica de dicho método cuando se agregó, sinonjses decir callsFake(), además, para las versiones anteriores, ¿cómo se puede desaprobar?
aitchkhan
3
Al usar módulos ES6: estoy creando el stub de YourClass.get () en un proyecto de prueba. La prueba llama a otro módulo que importa YourClass. ¿Respetará el módulo YourClass.get () el stub? Si no es así, ¿hay alguna solución?
Estudiante
1
Tus soluciones funcionan para mí. Deseo si le doy más puntos: D Gracias.
Rubel Hasan
5

Me encontré con el mismo error al intentar burlarme de un método de una clase CoffeeScript usando Sinon.

Dada una clase como esta:

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

Puede reemplazar su método con un espía de esta manera:

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

# ...

assert.ok(mySpy.called)

Simplemente reemplácelo spycon stubo mocksegún sea necesario.

Tenga en cuenta que deberá reemplazar assert.okcon cualquier afirmación que tenga su marco de prueba.

Nathan Arthur
fuente
2

Gracias a @loganfsmyth por el dato. Pude hacer que el stub funcionara en un método de clase Ember como este:

sinon.stub(Foo.prototype.constructor, 'find').returns([foo, foo]);
expect(Foo.find()).to.have.length(2)
Scott Nedderman
fuente
3
Este es un comentario. Comienza con un agradecimiento a otra respuesta y termina con una duplicación de su código.
michelpm
5
No parece una duplicación, aquí está Foo.prototype.constructor, donde está como en la respuesta original Sensor.prototype. Por otra parte, Foo.prototype.constructorno funciona para mí. :)
shaunc