Bagaimana cara saya menguji unit metode repositori yang diimplementasikan dengan Entity Framework?

Saya memiliki metode seperti ini di lapisan repositori saya:

public IEnumerable<User> GetActiveUsers()
{
    return dbContext.Users
           .Where(u => u.IsActive)
           .OrderBy(u => u.Name)
           .ToList();
}

Haruskah saya menguji unit metode ini dengan mengejek DbContext atau haruskah saya mengujinya dengan database yang sebenarnya?

Saya tahu ini berhenti menjadi pengujian "unit" ketika saya menggunakan database aktual, tetapi saya tidak melihat ada gunanya mengejek DbContext untuk menguji metode repositori saya yang logikanya tipis dan biasanya hanya memanggil metode EF secara langsung.

Dan jika saya harus menggunakan database sebenarnya, apakah ada strategi standar untuk mengisi data pengujian di database sehingga pengujian berjalan secara independen dan tidak mengubah status apa pun di database?


person Saravana    schedule 05.04.2014    source sumber
comment
Saya belum melakukannya dengan Entity Framework (saya menggunakan NHibernate sebagai ORM) tetapi ketika saya harus menguji logika database saya menggunakan sqlite dengan database dalam memori.   -  person Claudio Redi    schedule 05.04.2014


Jawaban (4)


Mungkin bukan yang ingin Anda dengar, tetapi Anda tidak ingin mengejek DbContext. Saya tahu hal ini telah dilakukan setiap saat dan di EF6 bahkan menjadi lebih mudah dari sebelumnya. Masih banyak lagi antarmuka dan metode virtual yang tersedia untuk mengimplementasikan objek tiruan. Secara teknis itu tidak sulit.

Yang penting adalah perilakunya.

Bahkan dalam contoh kecil Anda, ada kemungkinan masalah. Tiruan DbSet akan melakukan penyortiran peka huruf besar-kecil. DbSet yang terhubung akan menerima data yang diurutkan dari database dan banyak kumpulan database tidak peka huruf besar-kecil. Jadi pengujian unit dapat memberikan hasil yang berbeda dibandingkan pengujian integrasi, bahkan dalam kasus yang tampaknya tidak signifikan ini.

Perbedaan antara LINQ dalam memori dan yang terhubung luar biasa. Secara pribadi, saya hanya melakukan tes integrasi untuk apa pun yang melibatkan kueri LINQ ke Entitas. Terlalu mudah untuk membuat grafik objek tiruan yang akan terlihat berbeda jika EF membuatnya. Dalam metode layanan saya, saya terkadang membuat pertanyaan yang cukup rumit, mungkin melibatkan Includes, mungkin dengan sengaja menghilangkan null penjaga, mengetahui bahwa pernyataan tersebut diterjemahkan ke dalam SQL, mungkin melibatkan beberapa pemuatan lambat atau mengandalkan perbaikan hubungan. Saya harus menyadari status entitas, masa hidup konteks, validasi yang dimulai saat menyimpan perubahan, konkurensi ... Saya hanya tidak percaya tes hijau ketika semuanya diolok-olok.

Tentu saja logika bisnis masih cukup untuk diuji dengan pengujian unit murni. Setelah Anda dapat membuat asumsi bahwa objek yang benar tersedia (karena Anda mengujinya secara terpisah dalam pengujian integrasi), Anda dapat menirunya dan menguji unit perilakunya di dalam memori.

person Gert Arnold    schedule 05.04.2014

Di sisi lain: informasi tambahan apa yang akan Anda peroleh dengan menyiapkan database dan mengujinya?

Saya hanya akan mengejek DbContext karena akan lebih mudah untuk mempertahankannya dan karena pada dasarnya tidak ada gunanya menguji unit panggilan Entity-Framework terhadap database.

Hal yang ingin Anda uji adalah apakah kueri LINQ Anda mengembalikan data dari sumber data atau tidak. Namun kueri LINQ yang diterjemahkan ke kueri SQL oleh EF adalah sesuatu yang tidak akan Anda pedulikan.

Anda dapat menganggapnya sebagai tes integrasi tambahan jika Anda benar-benar ingin menguji dependensi eksternal Anda tetapi EF sendiri sudah sangat andal jadi saya ragu ini akan berguna dalam hal apa pun.

person Jeroen Vannevel    schedule 05.04.2014

Jika IEnumerable GetActiveUsers diimplementasikan (dan seharusnya) sebagai antarmuka, dan kode yang Anda posting adalah kelas konkret yang mengimplementasikan antarmuka tersebut. Maka Anda biasanya akan menggunakan kerangka tiruan untuk meniru antarmuka yang Anda terapkan dan mengembalikan kumpulan hasil yang Anda siapkan.

Seperti yang disebutkan Jeroen, Anda biasanya tidak perlu menguji unit apa yang dilakukan kerangka entitas. Tes unit hanya menguji logika Anda, bukan logika perpustakaan lain (EF di sini).

person J.W.    schedule 05.04.2014
comment
Meskipun pengujian logika basis data menurut definisi berada di luar cakupan pengujian unit, dalam praktiknya, hasilnya cukup berguna mengingat sebagian besar kueri memiliki beberapa logika yang mungkin mengandung bug. Saya pribadi menggunakan sqllite untuk kasus ini. - person Claudio Redi; 05.04.2014
comment
Saya setuju, tapi saya tidak yakin EF terhadap sqlite berfungsi sama dengan EF terhadap sql server. Ini mungkin menghasilkan hasil yang berbeda. - person J.W.; 05.04.2014

Sesuatu yang perlu diingat ketika menulis Mock untuk DBContext Anda dan mengeksekusi Kueri LINQ Anda adalah bahwa mereka dijalankan terhadap objek konteks tiruan sebagai LINQ ke OBJEK, bukan LINQ ke Entitas... (EF6)...

Saya pribadi akan meluangkan waktu Anda untuk menguji perilaku tersebut. Julie Lerman memiliki seri @ pluralsight dan MSDN Mag online yang membahas cara menguji dbContext jika Anda harus.

person Warren LaFrance    schedule 02.08.2014