J'essayais de simuler une méthode avec des paramètres vararg en utilisant Mockito:
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));
Cela ne fonctionne pas, cependant si je le fais à la place:
when(a.b(anyInt(), anyInt())).thenReturn(b);
assertEquals(b, a.b(1, 2));
Cela fonctionne, malgré que j’ai complètement omis l’argument varargs lors de l’arrêt de la méthode.
Des indices?
Mockito 1.8.1 introduit anyVararg () Matcher :
when(a.b(anyInt(), anyInt(), Matchers.<String>anyVararg())).thenReturn(b);
Consultez également l'historique de cette opération: https://code.google.com/archive/p/mockito/issues/62
Edit nouvelle syntaxe après dépréciation:
when(a.b(anyInt(), anyInt(), ArgumentMatchers.<String>any())).thenReturn(b);
Une fonctionnalité quelque peu non documentée: si vous souhaitez développer un Matcher personnalisé qui corresponde aux arguments vararg, vous devez le faire implémenter org.mockito.internal.matchers.VarargMatcher
pour qu'il fonctionne correctement. C'est une interface de marqueur vide, sans laquelle Mockito ne comparera pas correctement les arguments lors de l'appel d'une méthode avec varargs à l'aide de votre Matcher.
Par exemple:
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);
S'appuyant sur la réponse d'Eli Levine, voici une solution plus générique:
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);
}
}
Ensuite, vous pouvez l'utiliser avec les tableaux de correspondance de hamcrest ainsi:
verify(a).b(VarArgMatcher.varArgThat(
org.hamcrest.collection.IsArrayContaining.hasItemInArray("Test")));
(Évidemment, les importations statiques rendront ceci plus lisible.)
S'appuyant sur la réponse de topchef,
Pour la version 2.0.31-beta, je devais utiliser Mockito.anyVararg au lieu de Matchers.anyVararrg:
when(a.b(anyInt(), anyInt(), Mockito.<String>anyVararg())).thenReturn(b);
Adapter la réponse de @topchef,
Mockito.when(a.b(Mockito.anyInt(), Mockito.anyInt(), Mockito.any())).thenReturn(b);
Selon les docs Java pour Mockito 2.23.4, Mockito.any () "Correspond à tout, y compris les valeurs null et varargs."
Dans mon cas, la signature de la méthode dont je veux capturer l'argument est la suivante:
public byte[] write(byte ... data) throws IOException;
Dans ce cas, vous devriez lancer vers tableau d'octets explicitement:
when(spi.write((byte[])anyVararg())).thenReturn(someValue);
J'utilise la version 1.10.19
de mockito
Vous pouvez également parcourir les arguments:
Object[] args = invocation.getArguments();
for( int argNo = 0; argNo < args.length; ++argNo) {
// ... do something with args[argNo]
}
par exemple, vérifiez leurs types et les diffusez correctement, ajoutez-les à une liste ou quoi que ce soit.