Visual Studio memungkinkan pengujian unit metode pribadi melalui kelas accessor yang dihasilkan secara otomatis. Saya telah menulis tes metode pribadi yang berhasil dikompilasi, tetapi gagal saat runtime. Versi kode yang cukup minimal dan tesnya adalah:
//in project MyProj
class TypeA
{
private List<TypeB> myList = new List<TypeB>();
private class TypeB
{
public TypeB()
{
}
}
public TypeA()
{
}
private void MyFunc()
{
//processing of myList that changes state of instance
}
}
//in project TestMyProj
public void MyFuncTest()
{
TypeA_Accessor target = new TypeA_Accessor();
//following line is the one that throws exception
target.myList.Add(new TypeA_Accessor.TypeB());
target.MyFunc();
//check changed state of target
}
Kesalahan runtime adalah:
Object of type System.Collections.Generic.List`1[MyProj.TypeA.TypeA_Accessor+TypeB]' cannot be converted to type 'System.Collections.Generic.List`1[MyProj.TypeA.TypeA+TypeB]'.
Menurut intellisense - dan karenanya saya kira kompiler - target adalah tipe TypeA_Accessor. Tetapi pada saat runtime itu adalah tipe TypeA, dan karenanya menambahkan daftar gagal.
Apakah ada cara saya bisa menghentikan kesalahan ini? Atau, mungkin lebih mungkin, apa saran orang lain (saya memperkirakan mungkin "jangan menguji metode pribadi" dan "tidak memiliki unit test memanipulasi keadaan objek").
c#
unit-testing
junichiro
sumber
sumber
Jawaban:
Ya, jangan Uji metode pribadi .... Gagasan uji unit adalah untuk menguji unit dengan 'API' publiknya.
Jika Anda merasa perlu menguji banyak perilaku pribadi, kemungkinan besar Anda memiliki 'kelas' yang bersembunyi di dalam kelas yang Anda coba uji, ekstrak dan uji dengan antarmuka publiknya.
Salah satu saran / alat Berpikir ..... Ada ide bahwa tidak ada metode yang harus pribadi. Berarti semua metode harus hidup pada antarmuka publik dari suatu objek .... jika Anda merasa perlu menjadikannya pribadi, kemungkinan besar tinggal di objek lain.
Nasihat ini tidak begitu berhasil dalam praktiknya, tetapi sebagian besar sarannya bagus, dan seringkali akan mendorong orang untuk menguraikan benda-benda mereka menjadi benda-benda yang lebih kecil.
sumber
Anda dapat menggunakan Kelas PrivateObject
sumber
"Tidak ada yang disebut sebagai standar atau praktik terbaik, mungkin itu hanya pendapat populer".
Hal yang sama juga berlaku untuk diskusi ini.
Itu semua tergantung pada apa yang Anda anggap unit, jika Anda berpikir UNIT adalah kelas maka Anda hanya akan mencapai metode publik. Jika Anda berpikir UNIT adalah jalur kode yang mengenai metode pribadi tidak akan membuat Anda merasa bersalah.
Jika Anda ingin memanggil metode pribadi, Anda bisa menggunakan kelas "PrivateObject" dan memanggil metode panggil. Anda dapat menonton video youtube mendalam ini ( http://www.youtube.com/watch?v=Vq6Gcs9LrPQ ) yang menunjukkan cara menggunakan "PrivateObject" dan juga membahas apakah pengujian metode pribadi logis atau tidak.
sumber
Pemikiran lain di sini adalah untuk memperluas pengujian ke kelas / metode "internal", memberikan lebih banyak rasa kotak putih dari pengujian ini. Anda dapat menggunakan InternalsVisibleToAttribute pada perakitan untuk mengekspos ini ke modul pengujian unit terpisah.
Dalam kombinasi dengan kelas tertutup, Anda dapat mendekati enkapsulasi sedemikian rupa sehingga metode pengujian hanya dapat dilihat dari perakitan metode Anda yang tidak terbaik. Pertimbangkan bahwa metode yang dilindungi dalam kelas tertutup adalah de facto pribadi.
Dan unit test:
sumber
Salah satu cara untuk menguji metode pribadi adalah melalui refleksi. Ini berlaku untuk NUnit dan XUnit, juga:
sumber
call methods
statis dan tidak statis ?Ermh ... Datang ke sini dengan masalah yang persis sama: Uji metode pribadi yang sederhana namun penting . Setelah membaca utas ini, tampaknya seperti "Saya ingin mengebor lubang sederhana ini dalam potongan logam sederhana ini, dan saya ingin memastikan kualitasnya memenuhi spesifikasi", dan kemudian muncul "Oke, ini tidak mudah. Pertama-tama, tidak ada alat yang tepat untuk melakukannya, tetapi Anda bisa membangun observatorium gelombang gravitasi di taman Anda. Baca artikel saya di http://foobar.brigther-than-einstein.org/ Pertama, tentu saja, Anda harus mengikuti beberapa kursus fisika kuantum tingkat lanjut, maka Anda perlu banyak nitrogenium yang sangat dingin, dan kemudian, tentu saja, buku saya tersedia di Amazon "...
Dengan kata lain...
Tidak, hal pertama yang pertama.
Setiap metode, baik itu swasta, internal, terlindungi, publik harus dapat diuji. Harus ada cara untuk mengimplementasikan tes tersebut tanpa basa-basi seperti yang disajikan di sini.
Mengapa? Tepatnya karena arsitektur menyebutkan sejauh ini dilakukan oleh beberapa kontributor. Mungkin pengulangan sederhana prinsip-prinsip perangkat lunak dapat menjernihkan beberapa kesalahpahaman.
Dalam hal ini, tersangka yang biasa adalah: OCP, SRP, dan, seperti biasa, KIS.
Tapi tunggu dulu. Gagasan membuat segala sesuatu tersedia untuk umum lebih bersifat kurang politis dan semacam sikap. Tapi. Ketika datang ke kode, bahkan di Komunitas Open Source saat itu, ini bukan dogma. Alih-alih, "menyembunyikan" sesuatu adalah praktik yang baik untuk membuatnya lebih mudah mengenal API tertentu. Anda akan menyembunyikan, misalnya, perhitungan inti dari blok bangunan termometer digital baru Anda untuk pasar - tidak untuk menyembunyikan matematika di belakang kurva yang diukur nyata untuk pembaca kode yang ingin tahu, tetapi untuk mencegah kode Anda menjadi tergantung pada beberapa, mungkin tiba-tiba pengguna penting yang tidak bisa menolak menggunakan kode pribadi, internal, dan terproteksi Anda sebelumnya untuk mengimplementasikan ide mereka sendiri.
Apa yang saya bicarakan?
Sangat mudah untuk memproklamirkan Zaman Aquarius atau apa yang disebut saat ini, tetapi jika sensor saya mendapatkan dari 1.0 ke 2.0, implementasi Translate ... dapat berubah dari persamaan linear sederhana yang mudah dimengerti dan "dikembalikan". dapat digunakan "untuk semua orang, untuk perhitungan yang cukup canggih yang menggunakan analisis atau apa pun, dan jadi saya akan memecahkan kode orang lain. Mengapa? Karena mereka tidak memahami prinsip pengkodean perangkat lunak, bahkan KIS.
Untuk membuat dongeng ini singkat: Kita perlu cara sederhana untuk menguji metode pribadi - tanpa basa-basi.
Pertama: Selamat tahun baru semuanya!
Kedua: Latih pelajaran arsitek Anda.
Ketiga: Pengubah "publik" adalah agama, bukan solusi.
sumber
Opsi lain yang belum disebutkan adalah hanya menciptakan kelas uji unit sebagai anak dari objek yang Anda uji. Contoh NUnit:
Ini akan memungkinkan pengujian mudah metode pribadi dan terlindungi (tetapi tidak diwariskan), dan itu akan memungkinkan Anda untuk menjaga semua tes Anda terpisah dari kode nyata sehingga Anda tidak menggunakan majelis uji untuk produksi. Mengubah metode pribadi Anda ke metode yang dilindungi akan diterima di banyak objek yang diwarisi, dan itu adalah perubahan yang cukup sederhana untuk dilakukan.
NAMUN...
Meskipun ini merupakan pendekatan yang menarik untuk memecahkan masalah tentang cara menguji metode tersembunyi, saya tidak yakin bahwa saya akan menganjurkan bahwa ini adalah solusi yang tepat untuk masalah dalam semua kasus. Tampaknya agak aneh untuk secara internal menguji suatu objek, dan saya menduga mungkin ada beberapa skenario bahwa pendekatan ini akan meledak pada Anda. (Objek yang tidak dapat diubah misalnya, mungkin membuat beberapa tes sangat sulit).
Sementara saya menyebutkan pendekatan ini, saya akan menyarankan bahwa ini lebih merupakan saran curah pendapat daripada solusi yang sah. Ambillah dengan sebutir garam.
EDIT: Saya merasa benar-benar lucu bahwa orang memilih jawaban ini, karena saya secara eksplisit menggambarkan ini sebagai ide yang buruk. Apakah itu berarti orang setuju dengan saya? Aku sangat bingung.....
sumber
Dari buku Bekerja Efektif dengan Legacy Code :
Cara untuk memperbaikinya, menurut penulis, adalah dengan membuat kelas baru dan menambahkan metode sebagai
public
.Penulis menjelaskan lebih lanjut:
Jadi, dalam batas-batas ini, satu-satunya pilihan nyata Anda adalah membuat metode
public
, baik di kelas saat ini atau yang baru.sumber
TL; DR: Ekstrak metode pribadi ke kelas lain, uji pada kelas itu; baca lebih lanjut tentang prinsip SRP (Prinsip Tanggung Jawab Tunggal)
Tampaknya Anda perlu mengekstrak ke
private
metode ke kelas lain; dalam hal ini seharusnyapublic
. Alih-alih mencoba mengujiprivate
metode ini, Anda harus mengujipublic
metode kelas ini.Kami memiliki skenario berikut:
Kita perlu menguji logika
_someLogic
; tetapi tampaknyaClass A
mengambil peran lebih dari yang dibutuhkan (melanggar prinsip SRP); hanya refactor menjadi dua kelasDengan cara ini
someLogic
dapat diuji pada A2; di A1 hanya membuat beberapa A2 palsu lalu menyuntikkan ke konstruktor untuk menguji bahwa A2 dipanggil ke fungsi bernamasomeLogic
.sumber
Dalam VS 2005/2008 Anda dapat menggunakan accessor pribadi untuk menguji anggota pribadi, tetapi cara ini menghilang di versi VS yang lebih baru
sumber