Saya memiliki sejumlah metode logika bisnis yang menyimpan dan mengambil (dengan memfilter) objek dan daftar objek dari cache.
Mempertimbangkan
IList<TObject> AllFromCache() { ... }
TObject FetchById(guid id) { ... }
IList<TObject> FilterByPropertry(int property) { ... }
Fetch..
dan Filter..
akan memanggil AllFromCache
mana yang akan mengisi cache dan kembali jika tidak ada dan kembali saja jika ada.
Saya biasanya menghindar dari unit yang menguji ini. Apa praktik terbaik untuk Pengujian Unit terhadap jenis struktur ini?
Saya menganggap mengisi cache pada TestInitialize dan menghapus pada TestCleanup tapi itu tidak terasa benar bagi saya, (mungkin itu bisa).
sumber
The Tunggal Tanggung Jawab Prinsip adalah teman terbaik Anda di sini.
Pertama-tama, pindahkan AllFromCache () ke kelas repositori dan beri nama GetAll (). Itu diambil dari cache adalah detail implementasi dari repositori dan tidak boleh diketahui oleh kode panggilan.
Ini membuat pengujian kelas penyaringan Anda menyenangkan dan mudah. Tidak lagi peduli dari mana Anda mendapatkannya.
Kedua, bungkus kelas yang mendapatkan data dari database (atau di mana pun) dalam pembungkus caching.
AOP adalah teknik yang bagus untuk ini. Ini salah satu dari beberapa hal yang sangat bagus.
Menggunakan alat-alat seperti PostSharp , Anda dapat mengaturnya sehingga metode apa pun yang ditandai dengan atribut yang dipilih akan di-cache. Namun, jika ini adalah satu-satunya hal yang Anda caching, Anda tidak perlu pergi sejauh memiliki kerangka kerja AOP. Hanya memiliki Repositori dan Pembungkus Caching yang menggunakan antarmuka yang sama dan menyuntikkan itu ke kelas panggilan.
misalnya.
Lihat bagaimana Anda telah menghapus pengetahuan implementasi repositori dari ProductManager? Lihat juga bagaimana Anda mematuhi Prinsip Tanggung Jawab Tunggal dengan memiliki kelas yang menangani ekstraksi data, kelas yang menangani pengambilan data, dan kelas yang menangani caching?
Anda sekarang dapat instantiate ProductManager dengan salah satu dari Repositori tersebut dan mendapatkan caching ... atau tidak. Ini sangat berguna nantinya ketika Anda mendapatkan bug yang membingungkan yang Anda duga adalah hasil dari cache.
(Jika Anda menggunakan wadah IOC, bahkan lebih baik. Seharusnya jelas cara beradaptasi.)
Dan, dalam tes ProductManager Anda
Tidak perlu menguji cache sama sekali.
Sekarang pertanyaannya menjadi: Haruskah saya menguji CachedProductRepository itu? Saya sarankan tidak. Cache ini cukup tidak pasti. Kerangka kerja melakukan hal-hal dengan itu yang di luar kendali Anda. Seperti, hanya menghapus barang-barang dari itu ketika sudah terlalu penuh, misalnya. Anda akan berakhir dengan tes yang gagal sekali dalam bulan biru dan Anda tidak akan pernah mengerti mengapa.
Dan, setelah melakukan perubahan yang saya sarankan di atas, benar-benar tidak banyak logika untuk diuji di sana. Tes yang sangat penting, metode penyaringan, akan ada di sana dan sepenuhnya disarikan dari detail GetAll (). GetAll () baru saja ... mendapatkan semuanya. Dari suatu tempat.
sumber
Pendekatan yang Anda sarankan adalah apa yang akan saya lakukan. Dengan uraian Anda, hasil metode harus sama apakah objek ada di cache atau tidak: Anda harus tetap mendapatkan hasil yang sama. Itu mudah untuk diuji dengan mengatur cache dengan cara tertentu sebelum setiap tes. Mungkin ada beberapa kasus tambahan seperti jika penunjuk adalah
null
atau tidak ada objek memiliki properti yang diminta; itu juga bisa diuji.Selain itu, Anda mungkin menganggapnya diharapkan bahwa objek tersebut ada dalam cache setelah metode Anda kembali, terlepas dari apakah itu ada dalam cache di tempat pertama. Ini kontroversial, karena beberapa orang (termasuk saya sendiri) berpendapat bahwa Anda peduli dengan apa yang Anda dapatkan kembali dari antarmuka Anda, bukan bagaimana Anda mendapatkannya (yaitu pengujian Anda bahwa antarmuka berfungsi seperti yang diharapkan, bukan karena ia memiliki implementasi khusus). Jika Anda menganggapnya penting, Anda memiliki kesempatan untuk mengujinya.
sumber
Sebenarnya, itulah satu-satunya cara yang benar untuk dilakukan. Itulah dua fungsi yang ada di sana: untuk mengatur prasyarat, dan membersihkan. Jika prasyarat tidak terpenuhi, program Anda mungkin tidak berfungsi.
sumber
Saya sedang mengerjakan beberapa tes yang menggunakan cache baru-baru ini. Saya membuat pembungkus di sekitar kelas yang bekerja dengan cache, dan kemudian memiliki pernyataan bahwa pembungkus ini dipanggil.
Saya melakukan ini terutama karena kelas yang ada yang bekerja dengan cache statis.
sumber
Sepertinya Anda ingin menguji logika caching, tetapi bukan populating logic. Jadi saya menyarankan agar Anda mengejek apa yang tidak perlu Anda uji - mengisi.
AllFromCache()
Metode Anda menangani pengisian cache, dan itu harus didelegasikan ke sesuatu yang lain, seperti pemasok nilai. Jadi kode Anda akan terlihat sepertiSekarang Anda dapat mengejek pemasok untuk pengujian, untuk mengembalikan beberapa nilai yang telah ditentukan. Dengan begitu, Anda dapat menguji pemfilteran dan pengambilan yang sebenarnya, dan tidak memuat objek.
sumber