Esboçando um método de classe com Sinon.js

99

Estou tentando criar um método de stub usando sinon.js, mas recebo o seguinte erro:

Uncaught TypeError: Attempted to wrap undefined property sample_pressure as function

Eu também fui para esta questão ( Stubbing e / ou mocking uma classe em sinon.js? ) E copiei e colei o código, mas recebo o mesmo erro.

Aqui está o meu 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());

Aqui está o jsFiddle ( http://jsfiddle.net/pebreo/wyg5f/5/ ) para o código acima e o jsFiddle para a questão do SO que mencionei ( http://jsfiddle.net/pebreo/9mK5d/1/ )

Fiz questão de incluir sinon em Recursos externos no jsFiddle e até mesmo no jQuery 1.9. O que estou fazendo de errado?

Paulo
fonte

Respostas:

155

Seu código está tentando criar um stub em uma função Sensor, mas você definiu a função em Sensor.prototype.

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

é essencialmente o mesmo que este:

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

mas é inteligente o suficiente para ver que Sensor["sample_pressure"]não existe.

Então, o que você gostaria de fazer é algo como:

// 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
fonte
1
Qual coisa está obsoleta?
loganfsmyth
sinon.stub (Sensor, "sample_pressure", function () {return 0})
danday74
Isso está na minha resposta porque a pergunta original perguntou especificamente sobre isso. Visto que minha resposta não sugere que seja a abordagem correta para começar, não tenho certeza do que você está me pedindo para mudar. .returns(0)já faz a mesma coisa que .callFake(() => 0).
loganfsmyth
1
Não parece que returnsestá obsoleto. sinonjs.org/releases/v3.0.0/stubs . @ danday74, forneça a referência.
allenhwkim
2
@ danday74 .stubcom uma função como o terceiro argumento é removido: github.com/sinonjs/sinon/blob/master/lib/sinon/stub.js#L17 Não há nada de errado com .returnsou .callsFake, portanto, não há nada de errado com esta resposta.
loganfsmyth
52

A principal resposta está obsoleta. Agora você deve usar:

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

Ou para métodos estáticos:

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

Ou para casos simples, use apenas retornos:

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

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

Ou se você deseja criar um método para uma instância:

const yourClassInstance = new YourClass();
sinon.stub(yourClassInstance, 'myMethod').returns({})
danday74
fonte
4
Seria ótimo se você pudesse mencionar a versão específica para o seu referido método quando ele foi adicionado, sinonjsou seja callsFake(), para as versões mais antigas, como isso pode ser descontinuado?
aitchkhan
3
Ao usar módulos ES6: Estou criando o stub de YourClass.get () em um projeto de teste. O teste chama outro módulo que importa YourClass. O módulo YourClass.get () respeitará o stub? Se não, existe uma solução?
Aluno de
1
Suas soluções funcionam para mim. Gostaria de lhe dar mais pontos: D Obrigado.
Rubel Hasan
5

Encontrei o mesmo erro ao tentar simular um método de uma classe CoffeeScript usando o Sinon.

Dada uma aula como esta:

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

Você pode substituir seu método por um espião desta forma:

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

# ...

assert.ok(mySpy.called)

Substitua spypor stubou mockconforme necessário.

Observe que você precisará substituir assert.okpor qualquer asserção que sua estrutura de teste tenha.

Nathan Arthur
fonte
2

Obrigado a @loganfsmyth pela dica. Consegui fazer o stub funcionar em um método de classe Ember como este:

sinon.stub(Foo.prototype.constructor, 'find').returns([foo, foo]);
expect(Foo.find()).to.have.length(2)
Scott Nedderman
fonte
3
Este é um comentário. Começa com um agradecimento a outra resposta e termina com uma duplicação de seu código.
michelpm
5
Não parece uma duplicação - aqui está Foo.prototype.constructor, onde como na resposta original está Sensor.prototype. Então, novamente, Foo.prototype.constructornão funciona para mim. :)
shaunc