Mocararto'da Varargs Nasıl Düzgün Eşleştirilir


152

Mockito kullanarak vararg parametreleri ile bir yöntem alay etmeye çalışıyorum:

interface A {
  B b(int x, int y, C... c);
}

A a = mock(A.class);
B b = mock(B.class);

when(a.b(anyInt(), anyInt(), any(C[].class))).thenReturn(b);
assertEquals(b, a.b(1, 2));

Bu işe yaramaz, ancak bunun yerine bunu yaparsanız:

when(a.b(anyInt(), anyInt())).thenReturn(b);
assertEquals(b, a.b(1, 2));

Bu işe yarar, buna rağmen yöntemi saplama sırasında varargs argümanını tamamen atladım.

Herhangi bir ipucu var mı?


sıfır varargs parametrelerinin geçtiği durumla eşleştiği için son örneğin işe yaraması oldukça önemsizdir.
topchef

Yanıtlar:


235

Mockito 1.8.1, AnyVararg () Eşleştiricisini tanıttı :

when(a.b(anyInt(), anyInt(), Matchers.<String>anyVararg())).thenReturn(b);

Bunun için geçmişe de bakın: https://code.google.com/archive/p/mockito/issues/62

Kullanımdan kaldırıldıktan sonra yeni sözdizimini düzenleyin:

when(a.b(anyInt(), anyInt(), ArgumentMatchers.<String>any())).thenReturn(b);

26
anyVararg()dönüş türü olarak Nesneye sahiptir. Herhangi bir değişken arg türüyle (ör. String ..., Integer ..., vb.) Uyumlu hale getirmek için açık bir döküm yapın. Örneğin, varsa doSomething(Integer number, String ... args)sahte / saplama kodunu benzer bir şeyle yapabilirsiniz when(mock).doSomething(eq(1), (String) anyVarargs()). Bu derleme hatasıyla ilgilenmelidir.
Psycho Punch

15
bilgi için anyVararg artık kullanımdan kaldırıldı: "@ 2.1.0 itibariyle tanımlandı any () kullan"
alexbt

5
Matchersorg.hamcrest.Matcherssınıfla ad çakışmasını önlemek için artık kullanımdan kaldırılmıştır ve büyük olasılıkla mockito v3.0 sürümünde kaldırılacaktır. ArgumentMatchersBunun yerine kullanın .
JonyD

31

Belgelenmemiş bir özellik: vararg argümanlarıyla eşleşen özel bir Eşleştirici geliştirmek istiyorsanız, org.mockito.internal.matchers.VarargMatcherdoğru çalışması için uygulamanız gerekir . Mockito'nun, Matcher'ınızı kullanarak varargs ile bir yöntem çağırırken argümanları doğru bir şekilde karşılaştırmayacağı boş bir işaretleyici arayüzü.

Örneğin:

class MyVarargMatcher extends ArgumentMatcher<C[]> implements VarargMatcher {
    @Override public boolean matches(Object varargArgument) {
        return /* does it match? */ true;
    }
}

when(a.b(anyInt(), anyInt(), argThat(new MyVarargMatcher()))).thenReturn(b);

7

Eli Levine'nin cevabına odaklanmak daha genel bir çözümdür:

import org.hamcrest.Description;
import org.hamcrest.Matcher;
import org.mockito.ArgumentMatcher;
import org.mockito.internal.matchers.VarargMatcher;

import static org.mockito.Matchers.argThat;

public class VarArgMatcher<T> extends ArgumentMatcher<T[]> implements VarargMatcher {

    public static <T> T[] varArgThat(Matcher<T[]> hamcrestMatcher) {
        argThat(new VarArgMatcher(hamcrestMatcher));
        return null;
    }

    private final Matcher<T[]> hamcrestMatcher;

    private VarArgMatcher(Matcher<T[]> hamcrestMatcher) {
        this.hamcrestMatcher = hamcrestMatcher;
    }

    @Override
    public boolean matches(Object o) {
        return hamcrestMatcher.matches(o);
    }

    @Override
    public void describeTo(Description description) {
        description.appendText("has varargs: ").appendDescriptionOf(hamcrestMatcher);
    }

}

Sonra hamcrest'in dizi eşleştiricileri ile kullanabilirsiniz:

verify(a).b(VarArgMatcher.varArgThat(
            org.hamcrest.collection.IsArrayContaining.hasItemInArray("Test")));

(Açıkça statik ithalat, bunu daha okunabilir hale getirecektir.)


Güzel. Bu Mockito IMO içine inşa edilmelidir.
bryant

Böyle bir şey eklemek için Hamcrest'e karşı bir dava açtım. Bkz. Github.com/mockito/mockito/issues/356
Mark

Bu Mockito 1 için mi? 2.10'a karşı derlemeye çalışırken çeşitli derleme hataları alıyorum.
Frans

@Frans, bu yanıtı yazdığımda 2 sürümün hala beta sürümündeydi, bu yüzden evet muhtemelen Mockito v1.10.19 veya çevresinde yazılmıştır. ( github.com/mockito/mockito/releases ) Muhtemelen güncellenebilir ... :-D
Peter Westmacott

3

Kodu Peter Westmacott'un cevabında kullanıyorum, ancak Mockito 2.2.15 ile şimdi aşağıdakileri yapabilirsiniz:

verify(a).method(100L, arg1, arg2, arg3)

arg1, arg2, arg3varargs nerede .


1

Topchef'in cevabına dayanarak,

2.0.31-beta için Matchers.anyVararrg yerine Mockito.anyVararg kullanmak zorunda kaldım:

when(a.b(anyInt(), anyInt(), Mockito.<String>anyVararg())).thenReturn(b);

3
bilgi için anyVararg artık kullanımdan kaldırıldı: "@ 2.1.0 itibariyle tanımlandı any () kullan"
alexbt

0

Benim durumumda, argümanını yakalamak istediğim yöntemin imzası:

    public byte[] write(byte ... data) throws IOException;

Bu durumda, bayt dizisine açıkça yayın yapmalısınız :

       when(spi.write((byte[])anyVararg())).thenReturn(someValue);

Mockito sürümünü kullanıyorum 1.10.19


0

Ayrıca, bağımsız değişkenler arasında geçiş yapabilirsiniz:

Object[] args = invocation.getArguments(); 
for( int argNo = 0; argNo < args.length; ++argNo) { 
    // ... do something with args[argNo] 
}

örneğin, türlerini kontrol edin ve uygun şekilde yayınlayın, bir listeye veya her neyse ekleyin.


0

Cevabı @topchef'ten uyarlayarak,

Mockito.when(a.b(Mockito.anyInt(), Mockito.anyInt(), Mockito.any())).thenReturn(b);

Mockito 2.23.4 için java dokümanlarına göre Mockito.any () "null ve varargs dahil her şeyi eşleştirir."


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.