Mockito: Sınırlı Jokerlerle Tip Dönen Stubbing Yöntemleri


135

Bu kodu düşünün:

public class DummyClass {
    public List<? extends Number> dummyMethod() {
        return new ArrayList<Integer>();
    }
}
public class DummyClassTest {
    public void testMockitoWithGenerics() {
        DummyClass dummyClass = Mockito.mock(DummyClass.class);
        List<? extends Number> someList = new ArrayList<Integer>();
        Mockito.when(dummyClass.dummyMethod()).thenReturn(someList); //Compiler complains about this
    }
}

Derleyici, davranışı saplamaya çalışan satırdan şikayetçi dummyMethod(). Sınırlı joker karakterler ile bir tür döndüren stubbing yöntemleri hakkında nasıl bir işaret?


Kod snippet'inizi genel türleri gösterecek şekilde güncelleyebilir misiniz?
millhouse

1
Bitti. Ben ön ve kod etiketleri kaldırmak zorunda kaldı, sıyırma <? Sayı> 'yı tür bildiriminden uzatır.
Shikhar Mishra

Yanıtlar:


190

Bu amaçla doReturn türü olmayan güvenli yöntemi de kullanabilirsiniz ,

@Test
public void testMockitoWithGenerics()
{
    DummyClass dummyClass = Mockito.mock(DummyClass.class);
    List<? extends Number> someList = new ArrayList<Integer>();

    Mockito.doReturn(someList).when(dummyClass).dummyMethod();

    Assert.assertEquals(someList, dummyClass.dummyMethod());
}

Mockito'nun google grubunda tartışıldığı gibi .

Bu daha basit olsa da thenAnswer, yine güvenli bir tür olmadığını unutmayın. Tip güvenliği konusunda endişeleriniz varsa, tesisin cevabı doğru.

ek detaylar

Açık olmak gerekirse, derlenen derleyici hatası,

The method thenReturn(List<capture#1-of ? extends Number>) in the type OngoingStubbing<List<capture#1-of ? extends Number>> is not applicable for the arguments (List<capture#2-of ? extends Number>)

Derleyici whençağrı sırasında ilk joker türü atadı ve sonra çağrı ikinci joker türü thenReturnaynı olduğunu teyit edemez inanıyorum .

Görünüşe göre , yakalanması gereken bir joker olmayan thenAnswertürü alırken bir joker karakter türünü kabul ettiği için bu sorunla karşılaşmaz thenReturn. Mockito'nun Devam Eden Stubbinginden ,

OngoingStubbing<T> thenAnswer(Answer<?> answer);
OngoingStubbing<T> thenReturn(T value);

bu da bana kısmen yardımcı oluyor ... ama geri dönmeyi umduğunuz liste boş değilse ne olur?
ttati

boş bir liste yapmak yerine şunları da yapabilirsiniz: List <Number> someList = new ArrayList <Integer> (); someList.add (aNumber);
ttati

32

someListBazı bilinen değerlerle yüklenmek istediğinizi varsayıyorum ; işte Answer<T>her şeyi güvenli tutmak için şablonlanmış bir yardımcı yöntemle birlikte kullanılan bir yaklaşım :

@Test
public void testMockitoWithGenericsUsingAnswer()
{
    DummyClass dummyClass =  Mockito.mock(DummyClass.class);

    Answer<List<Integer>> answer = setupDummyListAnswer(77, 88, 99);
    Mockito.when(dummyClass.dummyMethod()).thenAnswer(answer);

    ...
}

private <N extends Number> Answer<List<N>> setupDummyListAnswer(N... values) {
    final List<N> someList = new ArrayList<N>();

    someList.addAll(Arrays.asList(values));

    Answer<List<N>> answer = new Answer<List<N>>() {
        public List<N> answer(InvocationOnMock invocation) throws Throwable {
            return someList;
        }   
    };
    return answer;
}

17

Dün aynı şeyi vurdum. @ Nondescript1 ve @millhouse'dan gelen her iki yanıt da bir çözüm bulmamda bana yardımcı oldu. Ben hatam bir java.util.List, ama neden değildi çünkü biraz daha genel yapılmış dışında hemen hemen, millhouse ile aynı kodu kullandım com.google.common.base.Optional. Benim küçük yardımcı yöntemi bu nedenle Tsadece değil , her türlü izin verir List<T>:

public static <T> Answer<T> createAnswer(final T value) {
    Answer<T> dummy = new Answer<T>() {
        @Override
        public T answer(InvocationOnMock invocation) throws Throwable {
            return value;
        }
    };
    return dummy;
}

Bu yardımcı yöntemle şunları yazabilirsiniz:

Mockito.when(dummyClass.dummyMethod()).thenAnswer(createAnswer(someList));

Bu sadece iyi derler ve thenReturn(...)yöntemle aynı şeyi yapar .

Birisi Java derleyicisinin yaydığı hatanın bir derleyici hatası olup olmadığını veya kodun gerçekten yanlış olup olmadığını biliyor mu?


Bu basit, basit ve anlayabildiğim kadarıyla doğru görünüyor. Mockito neden buna benzer bir şey sunmuyor emin değilim ....... sürece?
vacao

14
Java 8'de kısaltılabilir:, Mockito.when(dummyClass.dummyMethod()).thenAnswer(x -> someList)bu nedenle yardımcı program yöntemine gerek yoktur
fikovnik

1
@fikovnik Ne harika bir keşif "thenAnswer"!
borjab

5

Dönüyorum fikovnik 'ın yorumunu ben Java 8+ kullanarak en zarif çözüm olduğunu düşünüyorum olarak ona daha fazla görünürlük vermek için burada bir cevap içine.

Mockito dokümantasyon kullanılmasını önerir doReturn()(kabul yanıt önerildiği gibi) sadece son çare olarak.

Bunun yerine, soruda açıklanan derleyici hatasını atlatmak için, önerilen Mockito when()yaklaşımı thenAnswer()ve bir lambda (bir yardımcı yöntem yerine) ile kullanılabilir:

Mockito.when(mockedClass.mockedMethod()).thenAnswer(x -> resultList)

herhangi bir derleme zamanı hatası vermese de, girişleri içeren bir liste geçirirken bile döndürülen liste boştur.
Venkatesh Kolla - user2742897

0

Marek Radonsky tarafından önerilen fayda yöntemi işe yarıyor olsa da, fikovnik tarafından önerilen (IMHO garip görünümlü) lambda ifadesini bile gerektirmeyen başka bir seçenek daha var:

As Bu yanıt benzer bir soru gösterilere, ayrıca aşağıdakileri kullanabilirsiniz:

BDDMockito.willReturn(someList).given(dummyClass).dummyMethod();
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.