Saya harap pertanyaan ini memberikan beberapa jawaban menarik karena itu salah satu yang mengganggu saya untuk sementara waktu.
Apakah ada nilai nyata dalam pengujian unit controller di ASP.NET MVC?
Yang saya maksud dengan itu adalah, sebagian besar waktu, (dan saya bukan jenius), metode pengontrol saya, bahkan pada sesuatu yang paling kompleks seperti ini:
public ActionResult Create(MyModel model)
{
// start error list
var errors = new List<string>();
// check model state based on data annotations
if(ModelState.IsValid)
{
// call a service method
if(this._myService.CreateNew(model, Request.UserHostAddress, ref errors))
{
// all is well, data is saved,
// so tell the user they are brilliant
return View("_Success");
}
}
// add errors to model state
errors.ForEach(e => ModelState.AddModelError("", e));
// return view
return View(model);
}
Sebagian besar pekerjaan berat dilakukan oleh pipa MVC atau perpustakaan layanan saya.
Jadi mungkin pertanyaan yang akan diajukan:
- berapakah nilai unit yang menguji metode ini?
- tidakkah akan putus
Request.UserHostAddress
danModelState
dengan NullReferenceException? Haruskah saya mencoba mengejek ini? - jika saya refractor metode ini menjadi "helper" yang dapat digunakan kembali (yang mungkin saya harus, mengingat berapa kali saya melakukannya!), akan menguji yang bahkan berharga ketika semua saya benar-benar menguji sebagian besar "pipa" yang, mungkin, telah diuji dalam satu inci dari kehidupannya oleh Microsoft?
Saya pikir maksud saya sebenarnya , melakukan hal-hal berikut ini tampaknya sama sekali tidak ada gunanya dan salah
[TestMethod]
public void Test_Home_Index()
{
var controller = new HomeController();
var expected = "Index";
var actual = ((ViewResult)controller.Index()).ViewName;
Assert.AreEqual(expected, actual);
}
Jelas saya menjadi tumpul dengan contoh berlebihan yang tidak ada gunanya ini, tetapi apakah ada yang punya kebijaksanaan untuk menambahkan di sini?
Menantikan itu ... Terima kasih.
sumber
Jawaban:
Bahkan untuk sesuatu yang sangat sederhana, unit test akan melayani berbagai keperluan
Untuk tindakan tertentu saya akan menguji untuk yang berikut
Anda menunjukkan memeriksa Permintaan dan Model untuk NullReferenceException dan saya pikir ModelState.IsValid akan menangani penanganan NullReference untuk Model.
Mengejek Permintaan memungkinkan Anda untuk menjaga terhadap Permintaan Null yang secara umum tidak mungkin dalam produksi saya pikir, tetapi dapat terjadi dalam Tes Unit. Dalam Tes Integrasi itu akan memungkinkan Anda untuk memberikan nilai UserHostAddress berbeda (Permintaan masih input pengguna sejauh kontrol yang bersangkutan dan harus diuji sesuai)
sumber
Kontroler saya juga sangat kecil. Sebagian besar "logika" di controller ditangani menggunakan atribut filter (built-in dan tulisan tangan). Jadi pengontrol saya biasanya hanya memiliki beberapa pekerjaan:
ActionResult
Sebagian besar model mengikat dilakukan secara otomatis oleh ASP.NET MVC. DataAnnotations menangani sebagian besar validasi untuk saya juga.
Bahkan dengan begitu sedikit untuk diuji, saya masih biasanya menulisnya. Pada dasarnya, saya menguji apakah repositori saya dipanggil dan
ActionResult
jenis yang benar dikembalikan. Saya memiliki metode kenyamanan untukViewResult
memastikan jalur tampilan yang benar dikembalikan dan model tampilan terlihat seperti yang saya harapkan. Saya punya yang lain untuk memeriksa controller / action yang tepat diatur untukRedirectToActionResult
. Saya punya tes lain untukJsonResult
, dll. DllHasil yang tidak menguntungkan dari sub-
Controller
kelas kelas adalah bahwa ia menyediakan banyak metode kenyamanan yang menggunakanHttpContext
internal. Ini membuatnya sulit untuk menguji unit controller. Untuk alasan ini, saya biasanya meletakkanHttpContext
panggilan -dependen di belakang sebuah antarmuka dan meneruskan antarmuka itu ke konstruktor pengontrol (saya menggunakan ekstensi web Ninject untuk membuat pengontrol saya untuk saya). Antarmuka ini biasanya di mana saya menempel properti pembantu untuk mengakses sesi, pengaturan konfigurasi, IPrinciple dan URL helpers.Ini membutuhkan banyak uji tuntas, tetapi saya pikir itu sangat berharga.
sumber
BaseControllerTests
kelas di mana mereka semua tinggal. Saya mengejek repositori saya. Saya pasang mereka menggunakan Ninject.ActionResult
untuk memeriksa URL yang lewat, model, dll.Jelas beberapa pengendali jauh lebih kompleks dari itu tetapi berdasarkan murni pada contoh Anda:
Apa yang terjadi jika myService melempar pengecualian?
Sebagai catatan.
Juga, saya akan mempertanyakan kebijaksanaan melewati daftar dengan referensi (toh tidak perlu karena c # lolos dengan referensi, tetapi meskipun tidak) - meneruskan tindakan errorAction (Aksi) yang kemudian dapat digunakan oleh layanan untuk memompa pesan kesalahan ke yang kemudian dapat ditangani sesuai keinginan Anda (mungkin Anda ingin menambahkannya ke daftar, mungkin Anda ingin menambahkan kesalahan model, mungkin Anda ingin mencatatnya).
Dalam contoh Anda:
bukannya kesalahan ref, lakukan (string s) => ModelState.AddModelError ("", s) misalnya.
sumber