Menonaktifkan metode kelas dengan Sinon.js

99

Saya mencoba untuk menghentikan metode menggunakan sinon.js tetapi saya mendapatkan kesalahan berikut:

Uncaught TypeError: Attempted to wrap undefined property sample_pressure as function

Saya juga pergi ke pertanyaan ini ( Menghentikan dan / atau mengejek kelas di sinon.js? ) Dan menyalin dan menempelkan kode tetapi saya mendapatkan kesalahan yang sama.

Ini kode saya:

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

Ini adalah jsFiddle ( http://jsfiddle.net/pebreo/wyg5f/5/ ) untuk kode di atas, dan jsFiddle untuk pertanyaan SO yang saya sebutkan ( http://jsfiddle.net/pebreo/9mK5d/1/ ).

Saya memastikan untuk menyertakan sinon di Sumber Daya Eksternal di jsFiddle dan bahkan jQuery 1.9. Apa yang saya lakukan salah?

Paul
sumber

Jawaban:

155

Kode Anda mencoba menghentikan suatu fungsi Sensor, tetapi Anda telah menetapkan fungsi tersebut Sensor.prototype.

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

pada dasarnya sama dengan ini:

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

tetapi cukup pintar untuk melihat bahwa Sensor["sample_pressure"]itu tidak ada.

Jadi yang ingin Anda lakukan adalah seperti ini:

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

atau

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

atau

// 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
sumber
1
Hal mana yang tidak digunakan lagi?
loganfsmyth
sinon.stub (Sensor, "sample_pressure", function () {return 0})
danday74
Itu adalah jawaban saya karena pertanyaan asli secara khusus menanyakannya. Mengingat bahwa jawaban saya tidak menyarankan itu sebagai pendekatan yang benar untuk memulai, saya tidak yakin apa yang Anda minta untuk saya ubah. .returns(0)sudah melakukan hal yang sama seperti .callFake(() => 0).
loganfsmyth
1
Sepertinya itu tidak returnsusang. sinonjs.org/releases/v3.0.0/stubs . @ danday74, berikan referensi.
allenhwkim
2
@ danday74 .stubdengan fungsi sebagai argumen ketiga dihapus: github.com/sinonjs/sinon/blob/master/lib/sinon/stub.js#L17 Tidak ada yang salah dengan .returnsor .callsFake, jadi tidak ada yang salah dengan jawaban ini.
loganfsmyth
52

Jawaban teratas sudah tidak digunakan lagi. Anda sekarang harus menggunakan:

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

Atau untuk metode statis:

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

Atau untuk kasus sederhana, gunakan saja pengembalian:

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

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

Atau jika Anda ingin menghentikan metode sebagai contoh:

const yourClassInstance = new YourClass();
sinon.stub(yourClassInstance, 'myMethod').returns({})
danday74
sumber
4
Akan sangat bagus jika Anda dapat menyebutkan versi spesifik untuk metode yang Anda katakan ketika ini ditambahkan ke sinonjsie callsFake()terlebih lagi, untuk versi yang lebih lama bagaimana ini bisa dihentikan?
aitchkhan
3
Saat menggunakan modul ES6: Saya membuat rintisan YourClass.get () dalam proyek uji. Pengujian memanggil modul lain yang mengimpor YourClass. Akankah modul YourClass.get () menghormati stub? Jika tidak, apakah ada solusinya?
Pelajar
1
Solusi Anda berhasil untuk saya. Saya berharap jika saya memberi Anda lebih banyak poin: D Terima kasih.
Rubel hasan
5

Saya mengalami kesalahan yang sama saat mencoba meniru metode kelas CoffeeScript menggunakan Sinon.

Diberikan kelas seperti ini:

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

Anda dapat mengganti metodenya dengan mata-mata dengan cara ini:

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

# ...

assert.ok(mySpy.called)

Cukup ganti spydengan stubatau mocksesuai kebutuhan.

Perhatikan bahwa Anda harus mengganti assert.okdengan pernyataan apa pun yang dimiliki kerangka pengujian Anda.

Nathan Arthur
sumber
2

Terima kasih kepada @loganfsmyth untuk tipnya. Saya bisa mendapatkan rintisan untuk mengerjakan metode kelas Ember seperti ini:

sinon.stub(Foo.prototype.constructor, 'find').returns([foo, foo]);
expect(Foo.find()).to.have.length(2)
Scott Nedderman
sumber
3
Ini adalah sebuah komentar. Dimulai dengan ucapan terima kasih atas jawaban lain dan diakhiri dengan duplikasi kodenya.
michelpm
5
Tidak terlihat seperti duplikasi - ini ada Foo.prototype.constructor, sedangkan jawaban aslinya ada Sensor.prototype. Kemudian lagi, Foo.prototype.constructortidak berhasil untuk saya. :)
shaunc