Sorunuz MS Fakes çerçevesinin NMock'tan ne kadar farklı olduğuyla ilgiliydi ve diğer yanıtların bazılarını çözdüğü görülüyor, ancak burada nasıl aynı oldukları ve nasıl farklı oldukları hakkında biraz daha bilgi var. NMock ayrıca RhinoMocks ve Moq'a benzer, bu yüzden onları NMock ile gruplandırıyorum.
NMock / RhinoMocks / Moq ve MS Fakes Çerçevesi arasında hemen gördüğüm 3 büyük fark var:
MS sahte çerçevesi, genel türler yerine Visual Studio'nun önceki sürümlerindeki Accessors gibi, oluşturulan kodu kullanır. Bir bağımlılık için sahte çerçeveyi kullanmak istediğinizde, bağımlılığı içeren montajı test projesinin referanslarına eklersiniz ve ardından test çiftlerini (saplamalar veya şimler) oluşturmak için üzerine sağ tıklayın. Sonra test ederken, aslında bunun yerine bu oluşturulan sınıfları kullanıyorsunuz. NMock aynı şeyi (yani IStudentRepository studentRepository = mocks.NewMock<IStudentRepository>()
) başarmak için jenerik kullanır . Benim düşünceme göre, MS Fakes çerçeve yaklaşımı, gerçek arayüzünüzle değil, oluşturulan bir sınıfa karşı çalıştığınız için, kod gezintisini ve yeniden düzenlemeyi testler içinden engeller.
MS sahte çerçevesi saplamalar ve moller (şimler) sağlarken NMock, RhinoMocks ve Moq'un tümü saplamalar ve taklitler sağlar . MS'in alayları dahil etmeme kararını gerçekten anlamıyorum ve kişisel olarak aşağıda açıklanan nedenlerden dolayı ben hayranı değilim.
MS sahte çerçevesi ile, saplamak istediğiniz yöntemlerin alternatif bir uygulamasını sağlarsınız. Bu alternatif uygulamalar içinde, dönüş değerlerini belirtebilir ve yöntemin nasıl veya nasıl çağrıldığına ilişkin bilgileri izleyebilirsiniz. NMock, RhinoMocks ve Moq ile, sahte bir nesne oluşturursunuz ve ardından bu nesneyi stubed dönüş değerlerini belirtmek veya etkileşimleri izlemek için (yöntemlerin çağrılıp çağrılmadığı ve nasıl çağrıldığı) kullanırsınız. MS sahte yaklaşımını daha karmaşık ve daha az anlamlı buluyorum.
Çerçevelerin sağladıkları arasındaki farkı açıklığa kavuşturmak için: NMock, RhinoMocks ve Moq, iki tür test ikilisi (saplamalar ve alaylar) sağlar. Sahte çerçeve, saplamalar ve moller sağlar (bunlara şim denir) ve ne yazık ki taklitler içermez. NMock ve MS Fakes arasındaki farklılıkları ve benzerlikleri anlamak için, bu farklı test çiftlerinin ne olduğunu anlamak faydalı olacaktır:
Saplamalar: Saplamalar, test edilen yöntem tarafından test çiftlerinizden istenecek yöntemler veya özellikler için bir değer sağlamanız gerektiğinde kullanılır. Örneğin, test altındaki yöntemim IStudentRepository test doubleının DoesStudentExist () yöntemini çağırdığında, bunun true döndürmesini istiyorum.
NMock ve MS sahtelerindeki saplamalar fikri aynıdır, ancak NMock ile şunun gibi bir şey yaparsınız:
Stub.On(mockStudentRepository).Method("DoesStudentExist").Will(Return.Value(true));
Ve MSFakes ile şöyle bir şey yaparsınız:
IStudentRepository studentRepository = new DataAccess.Fakes.StubIStudentRepository() // Generated by Fakes.
{
DoesStudentExistInt32 = (studentId) => { return new Student(); }
};
MS Fakes örneğinde, DoesStudentExist yöntemi için tamamen yeni bir uygulama oluşturduğunuza dikkat edin (Sahte çerçeve, saplama nesnelerini oluştururken parametre veri türlerini yöntem adlarına eklediği için, buna DoesStudentExistInt32 denildiğine dikkat edin, bence bu, testler). Dürüst olmak gerekirse NMock uygulaması da beni rahatsız ediyor çünkü yöntem adını tanımlamak için bir dizge kullanıyor. (NMock'un nasıl kullanılacağını yanlış anladıysam affedin.) Bu yaklaşım yeniden düzenlemeyi gerçekten engelliyor ve bu nedenle NMock yerine RhinoMocks veya Moq'u şiddetle tavsiye ediyorum.
Taklitler: Taklitler, test edilen yönteminiz ile bağımlılıkları arasındaki etkileşimi doğrulamak için kullanılır. NMock ile, buna benzer beklentiler belirleyerek bunu yaparsınız:
Expect.Once.On(mockStudentRepository).Method("Find").With(123);
Bu, NMock yerine RhinoMocks ve Moq'u tercih etmemin bir başka nedenidir, NMock daha eski beklenti stilini kullanırken RhinoMocks ve Moq, testin sonunda böyle bir iddia olarak beklenen etkileşimleri belirttiğiniz Arrange / Act / Assert yaklaşımını destekler. :
stubStudentRepository.AssertWasCalled( x => x.Find(123));
Yine, RhinoMocks'un yöntemi tanımlamak için bir dize yerine bir lambda kullandığını unutmayın. Ms fakes çerçevesi hiç alay sağlamaz. Bu, daha sonra doğru ayarlandığını doğruladığınız değişkenleri ayarlamanız gerektiği anlamına gelir (yukarıdaki saplamalar açıklamasına bakın). Bu şuna benzer bir şeye benzeyecektir:
bool wasFindCalled = false;
IStudentRepository studentRepository = new DataAccess.Fakes.StubIStudentRepository()
{
DoesStudentExistInt32 = (studentId) =>
{
wasFindCalled = true;
return new Student();
}
};
classUnderTest.MethodUnderTest();
Assert.IsTrue(wasFindCalled);
Bu yaklaşımı, saplamadaki çağrıyı takip etmeniz ve daha sonra testte ileri sürmeniz gerektiğinden, biraz karmaşık buluyorum. NMock'u ve özellikle RhinoMocks örneklerini daha anlamlı buluyorum.
Moles (Şimler): Açıkçası, kötüye kullanım potansiyelleri nedeniyle benleri sevmiyorum. Birim testi (ve özellikle de TDD) hakkında çok sevdiğim şeylerden biri, kodunuzu test etmenin, nerede kötü kod yazdığınızı anlamanıza yardımcı olmasıdır. Bunun nedeni, kötü yazılmış kodun test edilmesinin zor olmasıdır. Bu, mol kullanırken doğru değildir çünkü benler aslında enjekte edilmeyen bağımlılıklara karşı test etmenize veya özel yöntemleri test etmenize izin vermek için tasarlanmıştır. Bunun gibi bir ShimsContext kullanmanız dışında, taslaklara benzer şekilde çalışırlar:
using (ShimsContext.Create())
{
System.Fakes.ShimDateTime.NowGet = () => { return new DateTime(fixedYear, 1, 1); };
}
Şimlerle ilgili endişem, insanların onları "birim testi yapmanın daha kolay bir yolu" olarak görmeye başlayacak olmalarıdır çünkü bu, sizi gerektiği gibi kod yazmaya zorlamaz. Bu kavram hakkında daha eksiksiz bir yazı için şu yazıma bakın:
Sahte çerçevelerle ilgili bazı endişeler hakkında daha fazla bilgi için şu gönderilere bir göz atın:
RhinoMocks'u öğrenmekle ilgileniyorsanız, işte bir Pluralsight eğitim videosu (tam açıklama - Bu kursu yazdım ve görüşler için telif ücreti alıyorum, ancak bu tartışma için geçerli olduğunu düşünüyorum, bu yüzden buraya dahil ediyorum):