Di Unit Testing, mengapa saya membuat Repository dua kali?

10

Suatu hari saya membaca sedikit tentang Unit Testing dan saya melihat beberapa contoh di mana orang membuat antarmuka repositori (yaitu IExampleRepository) dan kemudian membuat repositori nyata ( public class ExampleRepository : IExampleRepository) dan repositori yang akan digunakan untuk pengujian unit ( FakeExampleRepository : IExampleRepository).

Dalam IExampleRepositorymereka menerapkan metode yang sama seperti dalam ExampleRepository, namun dengan pertanyaan Linq yang berbeda.

Apa sebenarnya tujuan di sini? Saya pikir salah satu bagian dari unit menguji kode Anda adalah memastikan bahwa suatu metode berfungsi dengan benar? Tetapi ketika saya menggunakan dua pertanyaan yang sama sekali berbeda, satu untuk 'nyata' dan satu dalam tes, seberapa masuk akal tes ini?

jao
sumber

Jawaban:

8

Salah satu tujuan pengujian unit adalah untuk menguji hanya satu hal pada satu waktu yaitu kelas tunggal dan metode. Jika repositori itu sendiri tidak sedang diuji maka Anda biasanya akan mengejek ini dalam beberapa cara sehingga hanya untuk menguji logika dalam metode / kelas Anda.

Yang mengatakan Anda juga perlu menguji dengan repositori 'nyata' *, tetapi ini biasanya dilakukan dalam tes integrasi / sistem

* Jelas nyata seperti dalam repo yang diatur untuk pengujian, semoga tidak misalnya produksi DB.

jk.
sumber
Jadi dalam pengujian unit saya tidak akan menguji metode itu sendiri untuk memastikan bahwa ia mengembalikan nilai yang benar (berdasarkan set data palsu / diejek)?
jao
ya Anda akan menguji metode itu sendiri tetapi hanya kode dalam metode ini, kode dalam objek lain harus dibahas dalam tes unit lain, interaksi beberapa objek harus dibahas dalam tes integrasi atau tes tingkat yang lebih tinggi
jk.
1
Ok, jadi jika saya mengerti dengan benar, saya harus menggunakan repositori asli ketika unit menguji repositori. Saya tidak perlu mengujinya ketika saya sedang menulis unit test untuk Controllers (dalam hal Asp.Net MVC)
jao
4
@Theomax Tergantung pada konteksnya: jika Anda menguji unit komponen perangkat lunak yang bukan milik Anda ExampleRepository, maka yang terbaik adalah menggunakan tiruan. Pembenarannya adalah bahwa Anda tidak menguji unit repositori tetapi sesuatu yang lain.
Andres F.
5
@Theomax Untuk memperluas komentar AndresF: Jika Anda menguji unit ExampleRepository, gunakan hal yang nyata. Jika Anda menguji unit RepositoryController, maka itu hanya harus menggunakan FakeExampleRepositoryyang mengembalikan nilai yang ditentukan sebelumnya. Dengan cara ini, jika bug masuk ExampleRepository, hanya unit test yang akan gagal - RepositoryControllertes akan terus berhasil, jadi Anda tahu tidak ada bug di sana. Jika controller menggunakan repositori nyata, keduanya akan gagal dan Anda tidak akan tahu apakah Anda memiliki 1 bug atau 2.
Izkata
5

Saya setuju dengan dua jawaban dari jk. dan Jan Hudec - mereka memberikan informasi yang sangat bagus. Tapi saya pikir saya akan menambahkan sedikit.

Pertanyaan pertama Anda ("Apa sebenarnya tujuan di sini?") Penting. Jika Anda mendeskripsikan, tujuan sebenarnya adalah untuk menguji kelas yang menggunakan IExampleRepositoryantarmuka, bukan menguji implementasi repositori. Membuat FakeExampleRepositorymemungkinkan Anda untuk menguji kelas-kelas klien tanpa khawatir tentang rincian kelas repositori nyata.

Ini terutama benar jika objek yang Anda coba siapkan membuat pengujian sulit (mis. Mengakses sistem file, memanggil layanan web, atau berbicara ke database). Dengan menggunakan antarmuka (dan teknik lain semacam itu), Anda menjaga kopling tetap rendah. Oleh karena itu, kelas Xhanya perlu tahu tentang antarmuka dan tidak perlu tahu tentang detail implementasi. Tujuannya adalah memastikan bahwa kelas Xmelakukan hal yang benar.

Mengejek (atau mematikan, berpura-pura ... ada perbedaan perbedaan) adalah alat yang ampuh untuk pengujian unit dan TDD. Tapi itu bisa menyusahkan untuk secara manual membuat dan memelihara implementasi ini. Oleh karena itu, sebagian besar bahasa sekarang memiliki perpustakaan yang bisa mengejek untuk membantu. Karena Anda menggunakan C #, saya akan merekomendasikan Moq karena sederhana dan sangat kuat. Kemudian Anda dapat menguji antarmuka tanpa menumpuk kode tambahan untuk implementasi tiruan.

Allan
sumber
the real objective is to test the classes that are utilizing the IExampleRepository interfaceitu tidak sepenuhnya benar. Tujuannya adalah untuk mengujinya secara independen dari IExampleRepository. +1 untuk merekomendasikan kerangka isolasi yang baik.
StuperUser
1
Saya tidak setuju. Itu tidak terlepas dari IExampleRepositorykarena kelas yang diuji digabungkan ke antarmuka itu. Tetapi tidak tergantung pada implementasi antarmuka. Akan saya akui bahwa penjelasan saya mungkin bisa menggunakan sedikit lebih banyak kecakapan. :)
Allan
5

Apa sebenarnya tujuan di sini?

Isolasi.

Ide unit mengujinya untuk menguji unit kode sekecil mungkin . Anda melakukan ini dengan mengisolasinya dari semua kode produksi lainnya dalam pengujian.

Dengan membuat kelas palsu, satu-satunya kode produksi adalah kelas yang diuji.

Jika Anda membuat repositori palsu dengan benar dan pengujian gagal, Anda tahu bahwa masalahnya ada pada kode-dalam-tes. Ini memberi Anda manfaat diagnosis secara gratis.

Lihatlah kerangka kerja isolasi (seperti Moq seperti yang disarankan oleh @Allan) untuk dapat menghasilkan pemalsuan ini dengan cepat untuk mengatur kondisi pengujian dan menggunakannya untuk menegaskan.

StuperUser
sumber
Detail lebih lanjut tentang pemalsuan,
cemoohan
4

Ada tiga alasan mengapa Anda mungkin ingin memberikan contoh tiruan untuk unit test:

  1. Anda ingin membatasi ruang lingkup tes, sehingga tes tidak terpengaruh oleh bug di depndee, mungkin karena belum selesai atau tidak stabil atau Anda tidak ingin bug di orang lain memengaruhi tes Anda.
  2. Tanggungan rumit untuk diatur. Misalnya lapisan akses data sering dipermainkan, karena yang asli memerlukan pengaturan database pengujian. Anda masih perlu menguji lapisan akses data nyata, tetapi Anda dapat membatasi pengaturan mahal saat men-debug hal-hal lain.
  3. Untuk menguji bahwa kelas dependen bereaksi dengan benar terhadap berbagai jenis kesalahan, Anda memberikan versi tiruan yang mengembalikan semua jenis jawaban yang salah. Karena banyak mode kegagalan agak sulit direproduksi, tetapi harus tetap diuji.
Jan Hudec
sumber