Unit menguji metode batal

13

Untuk memperbaiki bug dalam aplikasi, saya memodifikasi metode yang dinamai postLogindengan menambahkan panggilan ke metode yang ada bernama getShoppingCart.

Kode

protected void postLogin() {
  getShoppingCart();
}

Namun, saya tidak yakin apa cara terbaik untuk menulis unit test postLogin.

Pendekatan 1

Gunakan verifikasi dari Mockito untuk memverifikasi bahwa metode itu dipanggil.

verify(mock).getShoppingCart();

Pendekatan 2

Uji efek samping dari pemanggilan metode dengan mengambil nilai keranjang belanja pengguna.

AssertNotNull(user.getShoppingCart());

Apakah satu pendekatan lebih baik dari yang lain?

A_B
sumber
1
mana yang membuat tes lebih mudah dimengerti, dan menjaga kode tetap bersih. Jika Anda tidak yakin dengan desain tes, itu BISA juga menjadi tanda bahwa desain kode tidak aktif. Pastikan Anda mengajukan pertanyaan ini: " MENGAPA menambahkan panggilan metode memperbaiki bug? Apakah ini cara yang BENAR untuk memperbaiki bug ini?"
Caleb
8
Kecuali jika getShoppingCart()metode Anda memiliki efek samping, Anda tidak perlu mengujinya. Jika memang memiliki efek samping, Anda harus benar-benar mengubah namanya karena getXXX()metode konvensional harus idempoten.
Jules
@ Jules getNextValue? Bisa dibilang, seseorang bisa mengatakan "Jangan menyebutnya rajin; ubah nama menjadi nextValue", tetapi saya telah melihat getNextdigunakan sebelumnya. Mungkin contoh yang lebih baik adalah objek yang mewakili elektron; apa yang terjadi ketika saya menelepon getPosition? Atau lebih buruk lagi,getPosition(); getVelocity();
Aaron

Jawaban:

18

Saya biasanya lebih suka metode 2.

Mengapa? Karena, Anda ingin postLoginmengubah keadaan sistem Anda, tetapi bagaimana hal itu menyelesaikan ini (dan metode apa yang dipanggil secara internal untuk ini) hanyalah detail implementasi, tidak ada pengujian unit Anda yang boleh membuat asumsi tentang apa pun. Jadi lebih baik lakukan tes Anda hanya memverifikasi keadaan akhir.

Doc Brown
sumber
4

Saya akan mengubah getShoppingCart menjadi sesuatu seperti initializeShoppingCart, tujuan metode ini harus jelas bagi siapa saja yang membacanya tanpa perlu memeriksa apa yang dilakukan metode ini dan efek samping seperti ini dapat menyebabkan perilaku mengejutkan bagi pengguna metode ini.

Jika getShoppingCart ada di kelas lain dan itu sudah diuji unit saya akan menggunakan pendekatan 1 - tidak perlu menguji lagi apa yang sudah diuji. Dalam hal ini kami yakin bahwa getShoppingCart berfungsi dengan baik dan kami hanya ingin memastikan bahwa itu dipanggil dari postLogin jadi jika seseorang di masa depan menghapus panggilan ini, tes akan gagal.

Jika getShoppingCart adalah metode pribadi yang tidak dapat diuji dengan sendirinya, maka saya akan menggunakan pendekatan 2, untuk memastikan bahwa ketika postLogin disebut fungsi yang diinginkan dari getShoppingCart dilakukan seperti yang diharapkan.

Nastya S
sumber
1

Saat menguji panggilan fungsi (batal atau tidak) yang memiliki efek samping, paling lengkap untuk menguji bahwa efek samping tidak hanya terjadi, tetapi untuk memeriksa bahwa efek samping (output sistem atau atau perubahan status) adalah yang diinginkan.

hotpaw2
sumber
1
Meskipun ini benar, perlu juga mempertimbangkan bahwa detail efek samping yang terjadi dapat menjadi bagian dari keadaan internal beberapa modul lain, dan bahwa dengan memeriksa detail tersebut Anda akan menggabungkan pengujian Anda untuk tidak hanya modul yang itu menguji tetapi juga modul lain, yang dapat menyebabkan tes rapuh jika detail tersebut cenderung berubah. Mengejek antarmuka antar modul membantu mencegah masalah ini.
Jules
0

Saya tidak akan membahas desain Anda, tetapi dalam kasus Anda, saya akan pergi untuk pendekatan pertama karena unit test adalah untuk menguji metode apa yang dilakukan secara teknis terlepas dari pekerjaan mereka di domain, yaitu, apa metode postLoginAnda? Secara teknis itu memanggil getShoppingCardsehingga Anda harus menguji yang benar-benar memanggil getShoppingCard, saya juga akan membuat tes lain untuk getShoppingCardmenguji apa yang dilakukannya dan jika memiliki efek samping saya akan memeriksanya di dalam tes baru itu.

La VloZ Merrill
sumber
0

Anda memiliki bug di postLogin. Jadi hal pertama yang harus Anda lakukan adalah membuat unit test yang setelah memanggil postLogin tanpa set informasi yang diharapkan akan "gagal".

Dari ide di atas, alternatif lain dari 2 yang diusulkan adalah menyuntikkan informasi tentang keranjang belanja sebagai parameter. Jika Anda tidak memiliki informasi yang benar, Anda melemparkan pengecualian yang tidak dicentang. Ini akan memperjelas bahwa tanpa detail yang benar, metode Anda akan hancur.

Ini akan memerlukan sedikit perubahan di mana klien yang memanggil postLogin sekarang juga diharuskan untuk lulus info keranjang belanja. Bagi saya ini masih koheren sekarang karena Anda melihat mereka digabungkan. Kopling ini akan dilakukan oleh pemanggil.

Maka Anda bahkan tidak perlu menguji getShoppingCart di dalam postLogin karena metode sebenarnya yang diuji adalah postLogin. Ini adalah salah satu yang memiliki bug dan satu-satunya yang membutuhkan perbaikan dan validasi yang tepat. Dengan ketergantungan yang disuntikkan, Anda akan dapat mengujinya dengan mudah dalam kondisi yang berbeda dan mengonfirmasi bahwa tidak ada kesalahan yang terjadi.

gumol
sumber