Pertanyaan Bagaimana cara menguji fungsi pribadi atau kelas yang memiliki metode pribadi, bidang, atau kelas batin?


Bagaimana saya menguji unit (menggunakan xUnit) kelas yang memiliki metode pribadi internal, bidang atau kelas bertingkat? Atau fungsi yang dibuat pribadi dengan memiliki hubungan internal (static di C / C ++) atau berada di pribadi (anonim) namespace?

Tampaknya buruk untuk mengubah pengubah akses untuk suatu metode atau fungsi hanya untuk dapat menjalankan tes.


2265


asal


Jawaban:


Jika Anda memiliki sedikit warisan Jawa aplikasi, dan Anda tidak diizinkan mengubah visibilitas metode Anda, cara terbaik untuk menguji metode pribadi adalah dengan menggunakan refleksi.

Secara internal kami menggunakan bantuan untuk mendapatkan / mengatur private dan private static variabel serta memanggil private dan private static metode. Pola berikut akan memungkinkan Anda melakukan hampir semua hal yang terkait dengan metode dan bidang pribadi. Tentu saja kamu tidak bisa berubah private static final variabel melalui refleksi.

Method method = targetClass.getDeclaredMethod(methodName, argClasses);
method.setAccessible(true);
return method.invoke(targetObject, argObjects);

Dan untuk bidang:

Field field = targetClass.getDeclaredField(fieldName);
field.setAccessible(true);
field.set(object, value);

Catatan:
  1 targetClass.getDeclaredMethod(methodName, argClasses) memungkinkan Anda melihat ke dalam private metode. Hal yang sama berlaku untuk    getDeclaredField.
  2. The setAccessible(true) diperlukan untuk bermain-main dengan swasta.


1416



Cara terbaik untuk menguji metode pribadi adalah melalui metode publik lain. Jika ini tidak dapat dilakukan, maka salah satu dari kondisi berikut ini benar:

  1. Metode pribadi adalah kode mati
  2. Ada bau desain dekat kelas yang Anda uji
  3. Metode yang Anda coba untuk menguji tidak boleh bersifat pribadi

506



Ketika saya memiliki metode pribadi di kelas yang cukup rumit sehingga saya merasa perlu menguji metode pribadi secara langsung, itu adalah bau kode: kelas saya terlalu rumit.

Pendekatan saya yang biasa untuk mengatasi masalah tersebut adalah dengan menggodaku kelas baru yang berisi bit-bit menarik. Seringkali, metode ini dan bidang yang berinteraksi dengan, dan mungkin metode lain atau dua dapat diekstrak ke kelas baru.

Kelas baru mengekspos metode ini sebagai 'publik', sehingga mereka dapat diakses untuk pengujian unit. Kelas baru dan lama sekarang lebih sederhana daripada kelas asli, yang sangat bagus untuk saya (saya harus menjaga hal-hal sederhana, atau saya tersesat!).

Perhatikan bahwa saya tidak menyarankan agar orang membuat kelas tanpa menggunakan otak mereka! Intinya di sini adalah menggunakan kekuatan pengujian unit untuk membantu Anda menemukan kelas baru yang baik.


271



Saya telah menggunakan refleksi untuk melakukan ini untuk Java di masa lalu, dan menurut saya itu adalah kesalahan besar.

Sebenarnya, Anda harus tidak akan menulis tes unit yang langsung menguji metode pribadi. Apa kamu harus sedang menguji adalah kontrak publik yang kelas miliki dengan objek lain; Anda tidak boleh langsung menguji internal objek. Jika pengembang lain ingin membuat perubahan internal kecil ke kelas, yang tidak mempengaruhi kelas kontrak publik, dia kemudian harus memodifikasi tes berdasarkan refleksi Anda untuk memastikan bahwa itu berfungsi. Jika Anda melakukan ini berulang kali di seluruh proyek, tes unit kemudian berhenti menjadi pengukuran yang berguna untuk kesehatan kode, dan mulai menjadi penghalang untuk pengembangan, dan gangguan bagi tim pengembangan.

Apa yang saya sarankan lakukan adalah menggunakan alat cakupan kode seperti Cobertura, untuk memastikan bahwa unit tes yang Anda tulis memberikan cakupan kode yang layak dalam metode pribadi. Dengan begitu, Anda secara tidak langsung menguji apa yang dilakukan oleh metode pribadi, dan mempertahankan tingkat kelincahan yang lebih tinggi.


229



Dari artikel ini: Pengujian Metode Swasta dengan JUnit dan SuiteRunner (Bill Venners), pada dasarnya Anda memiliki 4 opsi:

  • Jangan menguji metode pribadi.
  • Berikan akses paket metode.
  • Gunakan kelas tes bersarang.
  • Gunakan refleksi.

187



Umumnya tes unit dimaksudkan untuk melatih antarmuka publik kelas atau unit. Oleh karena itu, metode pribadi adalah detail implementasi yang tidak Anda harapkan untuk diuji secara eksplisit.


96



Hanya dua contoh di mana saya ingin menguji metode pribadi:

  1. Dekripsi dekripsi - Saya tidak akan ingin membuatnya terlihat oleh siapa saja untuk dilihat hanya untuk demi pengujian, siapa pun bisa gunakan mereka untuk mendekripsi. Tapi mereka intrinsik untuk kode, rumit, dan perlu selalu bekerja (pengecualian yang jelas adalah refleksi yang dapat digunakan untuk melihat bahkan metode pribadi dalam banyak kasus, kapan SecurityManager tidak dikonfigurasi untuk mencegah hal ini).
  2. Membuat SDK untuk komunitas konsumsi. Di sini publik mengambil sebuah arti yang sama sekali berbeda, karena ini adalah kode yang bisa dilihat seluruh dunia (bukan hanya internal untuk aplikasi saya). Saya taruh kode ke metode pribadi jika saya tidak ingin pengguna SDK melihatnya - I tidak melihat ini sebagai bau kode, hanya bagaimana cara kerja pemrograman SDK. Tapi dari Tentu saja saya masih perlu menguji saya metode pribadi, dan mereka di mana fungsi SDK saya sebenarnya hidup.

Saya mengerti ide hanya menguji "kontrak". Tapi saya tidak melihat seseorang dapat menganjurkan benar-benar tidak menguji kode - jarak tempuh Anda mungkin bervariasi.

Jadi tradeoff saya melibatkan menyulitkan JUnits dengan refleksi, daripada mengorbankan keamanan & SDK saya.


56



Metode privat disebut dengan metode publik, jadi input ke metode publik Anda juga harus menguji metode privat yang dipanggil oleh metode publik tersebut. Ketika metode publik gagal, maka itu bisa menjadi kegagalan dalam metode pribadi.


53