2011-12-14 14 views
19

bir oluşturucu alay etmek:Ben bir inşaatçı var nasıl mockito

class Builder{ 
    private String name; 
    private String address; 
    public Builder setName(String name){ 
     this.name = name; 
     return this; 
    } 
    public Builder setAddress(String address){ 
     this.address = address; 
     return this; 
    } 

} 

Mockito vasiyetinde oluşturucu alay ediyor her yöntem için beni boş verir. Bu nedenle, her işlevde kendini when().thenReturn kullanarak alay etmeden, her işlev çağrısında kendisinin geri dönmesini sağlamanın kolay bir yolu var.

+2

Gerçekten bununla dalga geçmek zorunda mısınız? Alay etmeye değecek bir çeşit bağımlılık gibi görünmüyor. Bir "hizmet" türü sınıftan ziyade bir "veri" türü sınıfına benziyor. Çok fazla gerçek davranışın olmadığı sınıflar yapmakta nadiren faydalı buluyorum. –

+1

Sadece bir örnek, gerçek oluşturucu biraz daha karmaşık ve sadece bu durumda test etmenize gerek yok. –

+1

Bunları ayırabilmeniz için *, * bir "aptal yapıcınız" (alay etmeye gerek yok) ve daha sonra alay etmek zorunda kaldığınız hizmet bölümü * var mı? –

cevap

8

Bir zincirleme API'sini alamak için RETURN_DEEP_STUBS kullanabilirsiniz.

Builder b = Mockito.mock(Builder.class, RETURNS_DEEP_STUBS); 
when(b.setName("a name").setAddress("an address")).thenReturn(b); 
assert b.setName("a name").setAddress("an address") == b; // this passes 

Ne yazık ki bu size "bütün değişik oluşturucu alay genel bir yol vermek olmaz: Eğer oluşturucu adı verilecek kesin emri biliyorsanız

, burada kullanmak nasıl bir örnek Yöntemler "böylece her zaman bunu geri döndürürler, diğer cevaplara bakın buna ihtiyacınız var.

+2

Ayrıca NB eğer derin saplama "yanlış" siparişi verirseniz ve sonucu yayınlarsanız, muhtemelen "java.lang.ClassCastException: org.mockito.internal.creation.jmock.ClassImposterizer $ ClassWithSuperclassToWorkAroundCglibBug gibi bazı garip mesajlar verirsiniz $$ EnhancerByMockitoWithCGLIB $$ 851828bd için kullanılamaz ... – rogerdpack

34

RETURN_DEEP_STUBS kullanımıyla ilgili sorun, her yöntem çağrıldığında farklı bir alay alacağınızdır. Sorunuzdan, doğru geri dönüş türüne sahip her bir yöntem için, çağrılan alayı döndüren bir varsayılan Cevap kullanmak istediğinizi düşünüyorum. Bu, aşağıdaki gibi bir şey olabilir. Bunu test etmediğimi, bu yüzden yazım hataları içerebilir, ancak umarım niyetin her durumda açık olmasını umuyorum. Sahibinizi oluşturduğunuzda, bunu varsayılan yanıtınız olarak belirtin. Daha sonra, alayınızı oluşturduğunuzda bunu varsayılan yanıtınız olarak belirtin. Bu, alayınızın kendisini yapabileceği her yöntemden geri getirmesini sağlar. Ancak, sahte tür için sahte olan bir yöntemi çağırdığınızda sıradan bir alay gibi davranacaktır.

yardımcı

@Mock(answer = SELF_RETURNING) private Builder mockBuilder; 

Hope gibi bir şey bu

Builder mockBuilder = mock(Builder.class, new SelfReturningAnswer()); 

gibi alay oluşturun veya bu sınıf için sabit oluşturmak ve yazmak.

+0

Emin misin? Derin stubbed alayımda ´verify´ kullanıyorum ve testleri geçiyorum. Bu nedenle, her kurucu yöntemini kullandığımda aynı örneği döndürmesi gerekir. –

+1

Evet, kesinlikle eminim.Yukarıda olduğu gibi Builder sınıfınız için bir test yazdım, RETURNS_DEEP_STUBS ile alay ettim, setAddress ve setName olarak adlandırdım. Testim, iki yöntem çağrısından dönen iki oyuncunun farklı olduğunu ileri sürdü. Testim geçti. –

+0

Testim http://pastebin.com/JNPrn4ng –

12

Mockito 2.0 (beta) sürümünden itibaren, RETURNS_SELF için neredeyse aynı şekilde David Wallace's answer olarak davranan yeni bir varsayılan yanıt var. Mockito dokümanlardan Örnek: Bu Mockito sınıfına ve Answers enum hem görünür, bu yüzden de @Mock(answer = RETURNS_SELF) sözdizimi ile uyumlu olacak ki

@Test 
public void use_full_builder_with_terminating_method() { 
    HttpBuilder builder = mock(HttpBuilder.class, RETURNS_SELF); 
    HttpRequesterWithHeaders requester = new HttpRequesterWithHeaders(builder); 
    String response = "StatusCode: 200"; 

    when(builder.request()).thenReturn(response); 

    assertThat(requester.request("URI")).isEqualTo(response); 
} 

Not.