zincirleme çağrısı için alay veya saplama

protected int parseExpire(CacheContext ctx) throws AttributeDefineException {
    Method targetMethod = ctx.getTargetMethod();
    CacheEnable cacheEnable = targetMethod.getAnnotation(CacheEnable.class);
    ExpireExpr cacheExpire = targetMethod.getAnnotation(ExpireExpr.class);
   //check for duplicate setting
    if (cacheEnable.expire() != CacheAttribute.DO_NOT_EXPIRE && cacheExpire != null) {
        throw new AttributeDefineException("expire are defined both in @CacheEnable and @ExpireExpr");
    }
   //expire time defined in @CacheEnable or @ExpireExpr
    return cacheEnable.expire() != CacheAttribute.DO_NOT_EXPIRE ? cacheEnable.expire() : parseExpireExpr(cacheExpire, ctx.getArgument());
}

test etme yöntemi budur

Method targetMethod = ctx.getTargetMethod();
CacheEnable cacheEnable = targetMethod.getAnnotation(CacheEnable.class);

Üç CacheContext, Yöntem ve CacheEnable ile alay etmeliyim. Test durumunu daha basit hale getirmek için bir fikrin var mı?

46

3 cevap

Mockito zincirleme taslakları işleyebilir :

Foo mock = mock(Foo.class, RETURNS_DEEP_STUBS);

// note that we're stubbing a chain of methods here: getBar().getName()
when(mock.getBar().getName()).thenReturn("deep");

// note that we're chaining method calls: getBar().getName()
assertEquals("deep", mock.getBar().getName());

AFAIK, zincirdeki ilk yöntem, ikinci zincirleme yöntem çağrısı üzerindeki değerinizi döndürecek şekilde ayarlanmış bir sahte döndürür.

Mockito'nun yazarları, bunun sadece eski kod için kullanıldığını belirtiyor. Aksi takdirde yapılacak daha iyi bir şey, bu davranışı CacheContext'inize aktarmak ve işi kendisinin yapmak için ihtiyaç duyduğu her türlü bilgiyi sağlamaktır. CacheContext'ten çektiğiniz bilgi miktarı, sınıfınızın kıskançlık özelliği olduğunu gösterir. .

101
katma
Cevabın üstündeki bağlantı bozuk.
katma yazar ajb, kaynak
Ama her zaman kıskançlık özelliği var mı? Büyük veriyi hafızada düzenleyen bir dto ağacım var. Bu ağaçtan veri okuyan ve üzerinde işlem yapan başka sınıflarım var. Onları test etmek için, dto - BTW ile dalga geçmem gerekiyor, gerçek dto'yu oluşturabilirim, ama aynı derecede hantal - derin saplama gerçekten bu durumda bana yardımcı oluyor. Burada bir şey özlüyor muyum? Kodumu daha iyi yapabilir miyim?
katma yazar Arash, kaynak
@Lunivore Fuar noktası. Her ne kadar bunu yapmanın bir seviyesi kabul edilebilir olsa da, ancak yöntemin muhtemelen büyük ölçüde istismar edildiğini anlıyorum. Kullanımdan vazgeçme adayı olup olmadığını merak ediyorum.
katma yazar Magnilex, kaynak
@Lunivore Yazarların, derin kodların sadece eski kod için kullanılmasının gerektiğini belirten resmi bir kaynağa işaret edebilir misiniz?
katma yazar Magnilex, kaynak
@Arash Her zaman özellik kıskançlık değildir. Vakanızda, bir modelin kalıcı katmana belirli bir DTO'da sunulduğu bir çeşit MVP modeli yaratmaya bakacağım. Şimdi sadece bir DTO değil, zengin bir nesneyiniz var. MVP gibi paternler, UI'lere göre kalıcılık için geçerlidir!
katma yazar Lunivore, kaynak
@VivekKothari Belki Mockito ekibine gönderebilir misin? github.com/mockito/mockito/issues
katma yazar Lunivore, kaynak
@Sammi Bu muhteşem bir küçük araç gibi görünüyor; Daha önce Reek'e rastlamadım. Ve ne harika bir isim ...: D
katma yazar Lunivore, kaynak
Evet. Bir sonraki eski kod adımı yöntemlerden birini doğru yere taşımak (eğer sorunu tamamen ortadan kaldırır, ancak daha sonra büyük miktarlarda sabitlemeye ihtiyaç duymak için bu tür şeylere yol açacaksa) yararlı olabilir.
katma yazar Lunivore, kaynak
@Magnilex Aslında resmi kaynakta . Kaynak kodunda olduğu gibi. "Çoğu senaryoda sahte bir geri dönüşün yanlış olduğunu lütfen unutmayın." Ayrıca: UYARI: Bu özellik düzenli temizlik kodu için nadiren gerekli olmalıdır! Eski kod için bırakın. Sahteciliğe geri dönmek için alay etmek, alay etmek için (...), Demeter Yasası'nın ihlali veya bir değer nesnesini (iyi bilinen bir anti-desen) alay ederek anlamlı ipuçları vermek. github.com/mockito/mockito/ blob/master/src/main/java/org/& hellip; (bunun çoğu 1393 satırında).
katma yazar Lunivore, kaynak
@Magnilex Eski kod etrafındaki sargı testleri, güvenli bir şekilde yeniden kalibre edebilmenin önemli bir parçasıdır. Temiz bir kod tabanına bir ara adım olarak sahip olmanın yanlış bir yanı yok.
katma yazar Lunivore, kaynak
@Magnilex Bunu söylediğimde, şu an için RETURNS_DEEP_STUBS kullanıyordum. Karmaşık bir arayüzü destekleyen bir yöntemle, Kotlin ve "by" anahtar kelimesini kullanarak alay edilmek istemediğim bir iç hashiye yönlendiren ... belki bu günlerde bunun için daha fazla kullanım var.
katma yazar Lunivore, kaynak
Tabii ki demek istediniz Mockito :)
katma yazar Lunivore, kaynak
@ajb Teşekkürler; sabit.
katma yazar Lunivore, kaynak
Szczepan, Mockito'yu yarattı çünkü beni ve bazılarını EasyMock'u kullanmak yerine elimizdeki mock'leri yuvarladı ve atasözlerinin BDD için daha iyi çalışması gerektiğine karar verdiler - tabii ki Mockito'yu tercih ederim! Ama o EasyMock yapmak için çatalladı, bu nedenle, evet, EasyMock harika. Devlerin omuzlarında duruyoruz ...
katma yazar Lunivore, kaynak
Bu ilginç ve ben çekildim. Ama sadece Foo foo = mock (Foo.class) kullanamazsınız; Bar çubuğu = sahte (Bar.class); zaman (foo.getBar ()) thenReturn (bar).; zaman (bar.getName ()). thenReturn '( "derin") . Gözlerime, okunması kolay ve "DERİN" saplama kavramını anlamak gerektirmez. (Btw, Mockito'yu severim.)
katma yazar cdunn2001, kaynak
Feture gıpta tanımı buraya taşındı: github.com/troessner/reek /blob/master/docs/Feature-Envy.md
katma yazar Sammi, kaynak
Zincirden biri genel bir tür döndürdüğünde bu çalışmaz. Bu sorunla karşılaşan başka biri var mı?
katma yazar Vivek Kothari, kaynak

JMockit'in ans'i tamamen kullanmasını daha kolay buldum. Kullanarak test durumlarına bakın:

https://github .com/ko5tik/andject/damla/ana/src/test/java/de/pribluda/android/andject/ViewInjectionTest.java

İşte ben Android SKD gelen ve tamamen gelen etkinlik temel sınıf, alay söndürdü. JMockit ile nihai, özel, soyut ya da başka bir şey olan şeylerle dalga geçebilirsiniz.

Test çantanızda şöyle görünecekti:

public void testFoo(@Mocked final Method targetMethod, 
                    @Mocked  final CacheContext context,
                    @Mocked final  CacheExpire ce) {
    new Expectations() {
       {
          //specify expected sequence of infocations here

           context.getTargetMethod(); returns(method);
       }
    };

   //call your method
    assertSomething(objectUndertest.cacheExpire(context))
3
katma
JMockit'in zincirli aramalar için özel bir notu olduğunu unutmayın: @Cascading . Ayrıca, bu gibi durumlarda, Beklentiler yerine NonStrictExpectations 'ı kullanmak isteyebilirsiniz. Bunun yerine, sahte yöntemlere yapılan çağrıların doğrulanması gerekmez.
katma yazar Rogério, kaynak
Cevabınız için düşünür, ama mockito'yu, herhangi bir şekilde kullanıyorum.
katma yazar jilen, kaynak
Teşekkürler, bu notu kaçırdım;) Ünite testlerimi basitleştirdim
katma yazar Konstantin Pribluda, kaynak

Test durumunuzu daha basit hale getirme önerim, yönteminizi yeniden düzenlemektir.

Her zaman kendimi bir yöntemi test etmede sorun yaşıyorum, benim için bir kod kokusu alıyorum ve neden test edilmesinin zor olduğunu soruyorum. Kod test edilmesi zorsa, kullanımı ve bakımı zor olabilir.

Bu durumda bunun nedeni, birkaç seviyeyi derinden geçen bir yöntem zincirine sahip olmanızdır. Belki ctx, cacheEnable ve cacheExpire parametreler olarak geçirin.

3
katma
Evet, ancak bu alanlar çalışma zamanında aop içeriğinden, çevreyi basitleştirmek zor.
katma yazar jilen, kaynak
Bunu JMockit'te yapmak için teknikler vardır. AOP alan enjeksiyonu simgeleyen nesnelerinizle alanlara atabilirsiniz. Veya provate alanlarını alaylı örneklerle başlatan deencapsulation tekniklerini kullanabilirsiniz
katma yazar Konstantin Pribluda, kaynak