Pertanyaan Anda adalah tentang bagaimana kerangka kerja MS Fakes berbeda dari NMock dan tampaknya jawaban lain telah menyelesaikan beberapa di antaranya, tetapi berikut adalah beberapa informasi lebih lanjut tentang bagaimana mereka sama dan bagaimana perbedaannya. NMock juga mirip dengan RhinoMocks dan Moq, jadi saya mengelompokkan mereka dengan NMock.
Ada 3 perbedaan utama yang saya lihat langsung antara NMock / RhinoMocks / Moq dan MS Fakes Framework:
Kerangka palsu MS menggunakan kode yang dihasilkan, seperti Accessors di versi Visual Studio sebelumnya, bukan tipe generik. Saat Anda ingin menggunakan kerangka kerja palsu untuk sebuah ketergantungan, Anda menambahkan rakitan yang berisi ketergantungan ke referensi proyek uji dan kemudian klik kanan padanya untuk menghasilkan uji ganda (rintisan atau shims). Kemudian saat Anda menguji, Anda sebenarnya menggunakan kelas yang dihasilkan ini sebagai gantinya. NMock menggunakan obat generik untuk mencapai hal yang sama (yaitu IStudentRepository studentRepository = mocks.NewMock<IStudentRepository>()
). Menurut pendapat saya, pendekatan kerangka kerja MS Fakes menghambat navigasi kode dan pemfaktoran ulang dari dalam pengujian karena Anda benar-benar bekerja dengan kelas yang dihasilkan, bukan antarmuka asli Anda.
Kerangka palsu MS menyediakan rintisan dan tahi lalat (shims), sedangkan NMock, RhinoMocks, dan Moq semuanya menyediakan rintisan dan tiruan . Saya benar-benar tidak mengerti keputusan MS untuk tidak memasukkan ejekan dan saya, secara pribadi bukan penggemar tahi lalat karena alasan yang dijelaskan di bawah ini.
Dengan kerangka kerja palsu MS, Anda menyediakan implementasi alternatif dari metode yang ingin Anda stub. Dalam implementasi alternatif ini, Anda dapat menentukan nilai yang dikembalikan dan melacak informasi tentang bagaimana atau jika metode itu dipanggil. Dengan NMock, RhinoMocks dan Moq, Anda menghasilkan objek tiruan dan kemudian menggunakan objek tersebut untuk menentukan nilai kembali yang dipotong atau untuk melacak interaksi (apakah dan bagaimana metode itu dipanggil). Saya menemukan pendekatan MS palsu lebih kompleks dan kurang ekspresif.
Untuk memperjelas perbedaan dalam apa yang disediakan kerangka kerja: NMock, RhinoMocks dan Moq semuanya menyediakan dua jenis tes ganda (rintisan dan tiruan). Kerangka palsu menyediakan rintisan dan tahi lalat (mereka menyebutnya shims), dan sayangnya tidak menyertakan tiruan. Untuk memahami perbedaan dan persamaan antara NMock dan MS Fakes, akan sangat membantu untuk memahami apa jenis tes ganda ini:
Stubs: Stub digunakan saat Anda perlu memberikan nilai untuk metode atau properti yang akan ditanyakan pada pengujian ganda Anda dengan metode yang diuji. Misalnya, ketika metode saya yang sedang diuji memanggil metode DoesStudentExist () dari tes ganda IStudentRepository, saya ingin mengembalikan nilai true.
Ide stubs di NMock dan MS palsu adalah sama, tetapi dengan NMock Anda akan melakukan sesuatu seperti ini:
Stub.On(mockStudentRepository).Method("DoesStudentExist").Will(Return.Value(true));
Dan dengan MSFakes Anda akan melakukan sesuatu seperti ini:
IStudentRepository studentRepository = new DataAccess.Fakes.StubIStudentRepository() // Generated by Fakes.
{
DoesStudentExistInt32 = (studentId) => { return new Student(); }
};
Perhatikan dalam contoh MS Fakes Anda membuat implementasi yang sama sekali baru untuk metode DoesStudentExist (Perhatikan bahwa ini disebut DoesStudentExistInt32 karena kerangka palsu menambahkan tipe data parameter ke nama metode saat menghasilkan objek rintisan, saya pikir ini mengaburkan kejelasan tes). Sejujurnya implementasi NMock juga mengganggu saya karena menggunakan string untuk mengidentifikasi nama metode. (Maafkan saya jika saya salah memahami bagaimana NMock dimaksudkan untuk digunakan.) Pendekatan ini benar-benar menghambat refactoring dan saya sangat merekomendasikan RhinoMocks atau Moq daripada NMock karena alasan ini.
Tiruan: Tiruan digunakan untuk memverifikasi interaksi antara metode Anda yang sedang diuji dan dependensinya. Dengan NMock, Anda melakukan ini dengan menetapkan ekspektasi yang serupa dengan ini:
Expect.Once.On(mockStudentRepository).Method("Find").With(123);
Ini adalah alasan lain mengapa saya lebih memilih RhinoMocks dan Moq daripada NMock, NMock menggunakan gaya ekspektasi yang lebih tua sedangkan RhinoMocks dan Moq keduanya mendukung pendekatan Atur / Bertindak / Tegaskan di mana Anda menentukan interaksi yang Anda harapkan sebagai pernyataan di akhir tes seperti ini :
stubStudentRepository.AssertWasCalled( x => x.Find(123));
Sekali lagi, perhatikan bahwa RhinoMocks menggunakan lambda, bukan string untuk mengidentifikasi metode tersebut. Kerangka ms fakes tidak menyediakan tiruan sama sekali. Ini berarti bahwa dalam implementasi yang dihentikan (lihat deskripsi stub di atas), Anda harus menyetel variabel yang nanti Anda verifikasi telah disetel dengan benar. Itu akan terlihat seperti ini:
bool wasFindCalled = false;
IStudentRepository studentRepository = new DataAccess.Fakes.StubIStudentRepository()
{
DoesStudentExistInt32 = (studentId) =>
{
wasFindCalled = true;
return new Student();
}
};
classUnderTest.MethodUnderTest();
Assert.IsTrue(wasFindCalled);
Saya menemukan pendekatan ini menjadi sedikit berbelit-belit karena Anda harus melacak panggilan di rintisan dan kemudian menegaskannya nanti dalam pengujian. Saya menemukan NMock, dan terutama RhinoMock, sebagai contoh yang lebih ekspresif.
Tahi Lalat (Shims): Terus terang, saya tidak suka tahi lalat, karena potensi mereka untuk disalahgunakan. Salah satu hal yang sangat saya sukai tentang pengujian unit (dan khususnya TDD) adalah pengujian kode Anda membantu Anda memahami di mana Anda telah menulis kode yang buruk. Ini karena pengujian kode yang ditulis dengan buruk itu sulit. Ini tidak benar saat menggunakan mol karena mol sebenarnya dirancang untuk memungkinkan Anda menguji dependensi yang tidak diinjeksi atau untuk menguji metode privat. Cara kerjanya mirip dengan stub, kecuali Anda menggunakan ShimsContext seperti ini:
using (ShimsContext.Create())
{
System.Fakes.ShimDateTime.NowGet = () => { return new DateTime(fixedYear, 1, 1); };
}
Kekhawatiran saya dengan shims adalah bahwa orang akan mulai melihat mereka sebagai "cara yang lebih mudah untuk pengujian unit" karena tidak memaksa Anda untuk menulis kode seperti yang seharusnya. Untuk tulisan yang lebih lengkap tentang konsep ini lihat posting saya ini:
Untuk informasi lebih lanjut tentang beberapa masalah yang terkait dengan kerangka palsu, lihat posting ini:
Jika Anda tertarik untuk mempelajari RhinoMocks, berikut adalah video pelatihan Pluralsight (pengungkapan penuh - Saya menulis kursus ini dan mendapatkan royalti untuk penayangan, tetapi menurut saya ini berlaku untuk diskusi ini, jadi saya memasukkannya di sini):