Apa yang Anda harapkan terjadi?
Ketika saya membuat tiruan di kelas dan mencoba mengontrol perilaku salah satu fungsinya menggunakan withArgs
, pengecualian dilemparkan. Terjadi hanya saat menggunakan beberapa panggilan withArgs
.
Apa yang sebenarnya terjadi?
Cara memperbanyakContoh yang dapat direproduksi
Asumsikan saya mendeklarasikan kelas C
:
class C {
static foo(arg1, arg2) {return 'foo';}
}
Saya mencoba mengontrol perilaku foo
menggunakan tiruan pada C
:
it('test withArgs mock', () => {
let CMock = sinon.mock(C);
let fooStub = CMock.expects('foo');
fooStub.withArgs('a', 'b').returns(1);
fooStub.withArgs('c', 'd').returns(2);
expect(fooStub('a', 'b')).toEqual(1);
expect(fooStub('c', 'd')).toEqual(2);
CMock.restore();
});
Yang melempar pengecualian berikut:
ExpectationError: foo menerima argumen yang salah ["a", "b"], diharapkan ["c", "d"]
di Object.fail (node_modules/sinon/lib/sinon/mock-expectation.js:281:25)
di Fungsi.(node_modules/sinon/lib/sinon/mock-expectation.js:182:33)
di Array.forEach (asli)
di Function.verifyCallAllowed (node_modules/sinon/lib/sinon/mock-expectation.js:175:27)
di Function.invoke (node_modules/sinon/lib/sinon/mock-expectation.js:78:14)
di proxy (node_modules/sinon/lib/sinon/spy.js:89:22)
Sementara kode ini berfungsi:
it('test withArgs stub', () => {
let fooStub = sinon.stub(C, 'foo');
fooStub.withArgs('a', 'b').returns(1);
fooStub.withArgs('c', 'd').returns(2);
expect(fooStub('a', 'b')).toEqual(1);
expect(fooStub('c', 'd')).toEqual(2);
fooStub.restore();
});
Perlu disebutkan bahwa skenario berikut berfungsi seperti yang diharapkan:
it('test one withArgs mock', () => {
let CMock = sinon.mock(C);
let fooStub = CMock.expects('foo');
fooStub.withArgs('a', 'b').returns(1);
expect(fooStub('a', 'b')).toEqual(1); // ok
CMock.restore();
});
it('test one withArgs mock', () => {
let CMock = sinon.mock(C);
let fooStub = CMock.expects('foo');
fooStub.withArgs('a', 'b').returns(1);
expect(fooStub('c', 'd')).toEqual(1); // error: foo received wrong arguments ["c", "d"], expected ["a", "b"]
CMock.restore();
});
Artinya, masalah hanya terjadi saat menggunakan withArgs
beberapa kali.
Ini mungkin terkait dengan #1381, tetapi seperti yang Anda lihat dalam contoh, solusi yang disarankan di sana tidak berfungsi.
Terima kasih atas contoh laporan masalah. Saya tidak menggunakan fungsionalitas tiruan, karena itu membuat otak saya sakit, jadi orang lain perlu melihat ini, tetapi contoh Anda akan membuatnya jauh lebih mudah.
Jangan ragu untuk melihat sendiri kodenya - seringkali cara tercepat untuk memperbaikinya :-)
Saya melihat kodenya.
Pertama-tama, tes ini berfungsi:
class C {
static foo(arg1, arg2) {return 'foo';}
}
it('test withArgs mock', () => {
let CMock = sinon.mock(C);
CMock.expects('foo').withArgs('a', 'b').returns(1);
CMock.expects('foo').withArgs('c', 'd').returns(2);
expect(C.foo('a', 'b')).toEqual(1);
expect(C.foo('c', 'd')).toEqual(2);
CMock.restore();
});
Ada dua alasan mengapa ini berhasil dan pengujian dalam edisi asli tidak:
expects
.expects
.Artinya, ini juga tidak berfungsi:
it('test withArgs mock', () => {
let CMock = sinon.mock(C);
CMock.expects('foo').withArgs('a', 'b').returns(1);
let fooStub = CMock.expects('foo').withArgs('c', 'd').returns(2);
expect(fooStub('a', 'b')).toEqual(1); // Error: foo received wrong arguments ["a", "b"], expected ["c", "d"]
expect(fooStub('c', 'd')).toEqual(2);
CMock.restore();
});
Mengapa itu terjadi?
Setiap kali expects
dipanggil, hal berikut terjadi:
minCalls/maxCalls
- yang merupakan variabel yang diubah ketika Anda memanggil once()
misalnya) dibuat, hanya saja itu adalah "rintisan lingkup", itu tidak memiliki koneksi ke expects
. Ini adalah objek yang dikembalikan dari expects
.Yang menghasilkan perilaku berbeda untuk skenario ini:
expects
, itu hanya akan terbatas pada expects
.expects
dan menemukan satu yang cocok. Jika ada lebih dari satu, itu akan memanggil yang pertama.Apakah ini perilaku yang benar? Bagi saya lebih intuitif bahwa begitu seseorang memanggil expects
pada suatu metode, itu akan berperilaku persis seperti stub
(dengan tambahan minCalls/maxCalls
). Ini akan mengakibatkan:
stub
dan mock-expectation
.Sekarang, apa yang akan terjadi pada minCalls/maxCalls
?
Karena hanya ada satu expectation
sekarang, saya mengusulkan tiga cara alternatif untuk melakukan verifikasi jumlah panggilan dengan tiruan:
once()
, twice()
dll. let fooStub = CMock.expects('foo').withArgs('a', 'b').returns(1).twice();
fooStub.withArgs('c', 'd').returns(2).once(); // Does not affect the previous expectation.
Meskipun mungkin agak membingungkan.
once()
, twice()
dll. CMock.expects('foo').withArgs('a', 'b').returns(1).twice(); // `twice()` returns `null`, so that one has to call `expects()` again to set expectations for other arguments.
CMock.expects('foo').withArgs('c', 'd').returns(2).once();
Lebih jelas, tetapi Anda tidak dapat mematikan foo
lebih dari sekali sehingga kami memerlukan cara untuk melewatinya. Juga, ini masih mungkin:
CMock.expects('foo').withArgs('a', 'b').returns(1).withArgs('c', 'd').returns(2).twice(); // I guess that this should only affect the last `withArgs`?
Masalah ini secara otomatis ditandai sebagai basi karena tidak ada aktivitas terbaru. Ini akan ditutup jika tidak ada aktivitas lebih lanjut yang terjadi. Terima kasih atas kontribusi Anda.
Komentar yang paling membantu
Saya melihat kodenya.
Pertama-tama, tes ini berfungsi:
Ada dua alasan mengapa ini berhasil dan pengujian dalam edisi asli tidak:
expects
.expects
.Artinya, ini juga tidak berfungsi:
Mengapa itu terjadi?
Setiap kali
expects
dipanggil, hal berikut terjadi:minCalls/maxCalls
- yang merupakan variabel yang diubah ketika Anda memanggilonce()
misalnya) dibuat, hanya saja itu adalah "rintisan lingkup", itu tidak memiliki koneksi keexpects
. Ini adalah objek yang dikembalikan dariexpects
.Yang menghasilkan perilaku berbeda untuk skenario ini:
expects
, itu hanya akan terbatas padaexpects
.expects
dan menemukan satu yang cocok. Jika ada lebih dari satu, itu akan memanggil yang pertama.Apakah ini perilaku yang benar? Bagi saya lebih intuitif bahwa begitu seseorang memanggil
expects
pada suatu metode, itu akan berperilaku persis sepertistub
(dengan tambahanminCalls/maxCalls
). Ini akan mengakibatkan:stub
danmock-expectation
.Sekarang, apa yang akan terjadi pada
minCalls/maxCalls
?Karena hanya ada satu
expectation
sekarang, saya mengusulkan tiga cara alternatif untuk melakukan verifikasi jumlah panggilan dengan tiruan:once()
,twice()
dll.Meskipun mungkin agak membingungkan.
once()
,twice()
dll.Lebih jelas, tetapi Anda tidak dapat mematikan
foo
lebih dari sekali sehingga kami memerlukan cara untuk melewatinya. Juga, ini masih mungkin: