Mock framework ve MS Fakes çerçeveleri


99

NMock ve VS 2011 Fakes Framework gibi Mock çerçevelerinin farklılıkları konusunda biraz kafa karıştırıcı. MSDN'den geçerken, anladığım kadarıyla Fakes, bağımlılıklarınızı RhinoMock veya NMock gibi taklit etmenize izin veriyor, ancak yaklaşım farklı, Fakes bu işlevselliği sağlamak için kod üretiyor ancak Mocks çerçevesi bunu yapmıyor. Yani benim anlayışım doğru mu? Sahte bir başka Mock çerçevesi mi

Yanıtlar:


189

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):


14
@Jim Birinin "enjekte edilmeyen bağımlılıklara karşı test etmesine" izin vermenin kötü bir şey olduğuna katılmıyorum. Aksine, pratikte bu yetenek, birçok anlamsız arayüz ve ilişkili "nesne kablolama" yapılandırması / karmaşıklığı ile bir kod tabanının dağınıklığını önlemeye yardımcı olur. Yalnızca tek bir uygulama sınıfıyla yüzlerce Java / C # arabirimine ve çok sayıda işe yaramaz XML yapılandırmasına (Spring DI fasulye için veya MS Unity için Web.config dosyasında) sahip birkaç proje (hem Java hem de .NET) gördüm. çerçeve). Bu tür bağımlılıkların enjekte edilmemesi daha iyidir .
Rogério

19
@Rogerio, bu modeli izleyen binlerce sınıfla birden fazla proje üzerinde çalıştım ve bağımlılık enjeksiyonu doğru yapıldığında (XML yapılandırmasını kullanıyorsanız doğru yapmıyorsunuz, imho), basit ve nispeten acısız. Öte yandan, bunu yapmayan sistemler üzerinde çalıştım ve sınıflar arası bağlantı bana her zaman ciddi bir acıya neden oldu. Bağımlılık ekleme kullanmanın nedeni test değildir (kötü bir neden olmasa da). Gerçek sebep, gevşemiş kaplindir. Tek bir sınıf tarafından uygulanan arayüzlere sahip olmak bana hiçbir zaman acı vermedi.
Jim Cooper

17
@ Jim, kötü tasarımı test etme yeteneğini harika bir artı olarak görüyorum. Eski kodu daha iyi bir tasarıma doğru yeniden düzenlemeden önce yapmak isteyeceğiniz ilk şey, test yazmaktır.
Thomas Materna

4
Benim kuralım, Fakes'i yalnızca paylaşılan / statik bir yöntemi veya bir arabirimi uygulamaya erişimim olmayan bir sınıfı Shim yapmam gerektiğinde kullanmam. Diğer her şey için Moq kullanıyorum. Sahte gruplar daha yavaştır (çünkü sahte montajların oluşturulması gerekir) ve Moq ile elde ettiğiniz işlevselliği eşleştirmek için daha fazla kodlama çabası gerekir.
Nick

5
Her şeyden CarloV.Dango Birinci @, ben gayet iyi Bağımlılık Enjeksiyon biliyoruz ki değil ayrı arayüzler gerektiren; önceki yorumum, DI kullanırken bu tür arayüzler yaratma eğilimini ima ediyordu. İkinci olarak, "IOC" (Ters Kontrol) 'ün DI ile hiçbir ilgisi yoktur ! (Birincisi yöntemler arasındaki kontrol akışının tersine çevrilmesi , ikincisi ise bir bileşen / nesne için bağımlılıkların çözümü ile ilgilidir.) IOC ve DI'yi karıştırarak, cehalet gösteren sizsiniz, ben değil; ve açıkçası, bu site insanların başkalarına hakaret etmeyi hak etmiyor, bu yüzden lütfen onu medeni tutalım.
Rogério

23

Haklısın, ama hikayenin dahası var. Bu cevaptan çıkarılması gereken en önemli şeyler şunlardır:

  1. Fakes ve alayların koltuk değneklerine güvenmek yerine, mimariniz taslakları ve bağımlılık enjeksiyonunu doğru şekilde kullanmalıdır

  2. Sahte ve taklitler, değiştirmemeniz veya değiştirememeniz gereken kodu test etmek için kullanışlıdır, örneğin:

    • Saplamaları kullanmayan (veya verimli kullanmayan) eski kod
    • 3. taraf API'leri
    • Kaynak kodunuz olmayan kaynaklar

Shims (geliştirme sırasında "Moles" olarak bilinir), gerçekten detoürasyon çağrıları yoluyla çalışan alaycı bir çerçevedir. Titizlikle bir taklit oluşturmak yerine (evet, Moq kullanmak bile nispeten zahmetli!), Şimler sadece zaten yerinde olan üretim kodu nesnesini kullanır. Şimler, çağrıyı üretim hedefinden test delegesine yeniden yönlendirir.

Stub'lar , hedef projedeki arayüzlerden oluşturulur. Stub nesnesi tam da budur - arayüzün bir uygulamasıdır. Saplama türünü kullanmanın yararı, test projenizi çok sayıda tek kullanımlık saplamalarla karıştırmadan hızlı bir şekilde bir saplama oluşturabilmenizdir, bunları oluşturmak için zaman kaybetmekten bahsetmiyorum bile. Elbette, birçok testte kullanmak için yine de somut saplamalar oluşturmalısınız.

Fakes'i (Shims, Mocks ve Stub türleri) verimli bir şekilde uygulamak, alışmak biraz zaman alır, ancak çabaya değer. Shims / Mole, Mocks ve Stub türlerini kullanarak kişisel olarak geliştirme süresinden haftalarca tasarruf ettim. Umarım teknoloji ile benim kadar eğlenirsiniz!


11
Fakes'teki yorumlarınızla ilgili ayrıntı eksikliği ve bazı terminoloji sorunları nedeniyle olumsuz oy verildi. Sahte, tüm test çiftleri türleri için genel bir terimdir ve ayrıca MS sahte kitaplıkları için kullanılan addır. Kütüphanelerinde sadece Şimler aslında Mollerdir, taslaklar değildir. Örneklere duyulan ihtiyaçla ilgili olarak, cevabınızda Fakes ile bir şim (veya saplama) oluşturmanın Moq kullanmaktan daha basit olduğunu gösteren bir örnek görmek isterim. Bunları çözmek için cevabınızda değişiklik yaparsanız, olumsuz oyumu değiştireceğim.
Jim Cooper

1
Ancak şimlerin (mol), yani 3. taraf kodu, sistem / SDK API'lerinin kullanımı için iyi bir gerekçe ekler. Bu sadece kendi şirket içi çözümlerinizle çalıştığınız zamanla ilgili değil. Bunu dengelemek için size bir oy vereceğim :-)
Tony Wall

2
@Mike ve Jim .. Bu cevapta kullanılan terminolojiyi düzeltmek için çaba sarf ettim. Daha iyi hale getirebilirsek lütfen bana bildirin. Teşekkürler.
Snesh

15

Anladığım kadarıyla, Visual Studio ekibi .NET için kullanılabilen çeşitli sahte kitaplıklarla rekabet etmekten kaçınmak istedi. MS genellikle bunun gibi zor kararlarla karşı karşıya kalır. Belli bir işlevsellik sağlamazlarsa ("MS neden bize sahte bir kitaplık sağlamaz; taklitler bu kadar yaygın bir gereksinimdir?") Ve yapmaları halinde de lanetlenirler ("Microsoft neden bu kadar agresif davranıyor ve piyasanın dışındaki doğal destekçiler? ") Çok sık, ancak her zaman değil, mevcut ve iyi karşılanan teknolojilere kendi alternatiflerini sunmaktan geri durmaya karar veriyorlar. Burada durum böyle görünüyor.

Fakes'in shim özelliği gerçekten çok kullanışlıdır. Elbette, tehlikeler var. Bunu yalnızca gerektiği yerde kullanmanızı sağlamak biraz disiplin gerektirir. Ancak büyük bir boşluğu doldurur. Benim ana şikayetim, yalnızca VS 2012'nin Ultimate sürümü ile birlikte sunulması ve bu nedenle yalnızca .NET geliştirme topluluğunun bir alt bölümü tarafından kullanılabilecek olmasıdır. Ne yazık.


2
Sahte çerçeve, Premium sürümde de mevcuttur.
AlwaysAProgrammer

13

Sahte iki farklı türde "sahte" nesne içerir. Birincisi, "saplama" olarak adlandırılan, esasen otomatik olarak oluşturulmuş bir kukla olup, varsayılan davranışı onu daha ilginç bir taklit haline getirmek için geçersiz kılınabilir (ve genellikle olurdu). Bununla birlikte, şu anda mevcut alay etme çerçevelerinin çoğunun sunduğu bazı özelliklerden yoksundur. Örneğin, bir saplama örneğindeki bir yöntemin çağrıldığını kontrol etmek istiyorsanız, bunun için mantığı kendiniz eklemeniz gerekir. Temel olarak, şimdi kendi taklitlerinizi manuel olarak yazıyorsanız, taslaklar muhtemelen bir gelişme gibi görünecektir. Bununla birlikte, zaten daha tam özellikli bir alay çerçevesi kullanıyorsanız, Sahte saplamalarda eksik olan bazı önemli parçalar olduğunu hissedebilirsiniz.

Fakes tarafından sunulan ve "shim" olarak adlandırılan diğer nesne kategorisi, taklitler yoluyla standart değiştirme için yeterince ayrıştırılmamış (veya yapılamayacak) bağımlılıkların davranışını değiştirmek için bir mekanizma ortaya koymaktadır. AFAIK, TypeMock şu anda bu tür bir işlevsellik sunan başlıca alay çerçevelerinden yalnızca biridir.

BTW, daha önce Moles'i denediyseniz, Fakes aslında aynı şeydir ve sonunda Microsoft Research'ten çıkıp gerçek bir ürüne dönüşür.


1
Güncelleme: Moles artık MS Fakes'e entegre edildi. "Visual Studio 2012'deki Fakes Çerçevesi, Moles ve Stubs'ın yeni neslidir. Sahte, Moles'ten farklıdır, bu nedenle Moles'ten Fakes'e geçmek kodunuzda bazı değişiklikler gerektirecektir. Moles çerçevesi, Visual Studio 2012'de desteklenmeyecektir. . " Kaynak: research.microsoft.com/en-us/projects/moles
Sire

1

Sahte (Shim + Stub) nesnelerle ilgili olarak, yukarıda iyi tanımlanmış olsa da, sanırım son yorumdaki son paragraf tüm durumu oldukça iyi özetlemektedir.

Pek çok kişi, Sahte (Shim + Stub) nesnelerin bazı birim test durumlarında sahip olunabilecek iyi varlıklar olduğunu iddia etse de, dezavantajı, Visual Studio 2012 veya Visual Studio 2013 kullanıyor olsanız da, bu seçenekler YALNIZCA kullanılabilir. Premium veya Ultimate sürümleri ile. IOW, bu, herhangi bir Pro sürümünde bu Sahtekarlıklardan (Shim + Stub) HİÇBİRİNİ ÇALIŞTIRMAYACAĞINIZ anlamına gelir.

Muhtemelen Pro sürümlerinde Sahte (Shim + Stub) menü seçeneğini görebilirsiniz, ancak dikkat edin, kesinlikle hiçbir şeyle sonuçlanmayacağınız konusunda oldukça güçlü şanslar vardır ... Size önemli bir şey olduğunu söyleyen herhangi bir derleme hatası oluşturmaz eksik, seçenekler yok, bu yüzden zamanınızı boşa harcamayın ...

Geliştirme ekibinde göz önünde bulundurulması gereken önemli bir faktördür, özellikle Ultimate sürümü kullanan tek kişi ve diğer herkes Pro sürümü kullanıyorsa ... Diğer yandan Moq, hangi Visual Studio sürümünü kullanırsanız kullanın Nuget aracılığıyla kolayca yüklenebilir. Moq'u kullanırken hiç sorun yaşamadım, herhangi bir aracın anahtarı, ne için kullanıldıklarını ve bunları nasıl doğru şekilde kullanacaklarını bilmektir;)


1
Lütfen sorunuzu daha kolay okunabilmesi için daha küçük paragraflar halinde biçimlendirin.

@SirXamelot, kodu yeniden düzenlemek yerine .net'in çıktısını değiştiremezsiniz, örneğin DateTime.Now veya Guid.NewGuid
zaitsman
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.