indefinidos - parametros infinitos java
Cómo hacer coincidir adecuadamente varargs en Mockito (7)
He estado intentando burlarme de un método con parámetros vararg usando 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));
Esto no funciona, sin embargo, si hago esto en su lugar:
when(a.b(anyInt(), anyInt())).thenReturn(b);
assertEquals(b, a.b(1, 2));
Esto funciona, a pesar de que he omitido por completo el argumento varargs al anular el método.
¿Alguna pista?
Basándose en la respuesta de Topchef,
Para 2.0.31-beta tuve que usar Mockito.anyVararg en lugar de Matchers.anyVararrg:
when(a.b(anyInt(), anyInt(), Mockito.<String>anyVararg())).thenReturn(b);
En mi caso, la firma del método que quiero capturar su argumento es:
public byte[] write(byte ... data) throws IOException;
En este caso, debe convertir a la matriz de bytes explícitamente:
when(spi.write((byte[])anyVararg())).thenReturn(someValue);
Estoy usando la versión 1.10.19
He estado usando el código en la respuesta de Peter Westmacott, pero con Mockito 2.2.15 ahora puede hacer lo siguiente:
verify(a).method(100L, arg1, arg2, arg3)
donde arg1, arg2, arg3
son varargs.
Mockito 1.8.1 introdujo cualquier matizador deVarrarg () :
when(a.b(anyInt(), anyInt(), Matchers.<String>anyVararg())).thenReturn(b);
Consulte también la historia de esto: https://code.google.com/archive/p/mockito/issues/62
Sobre la base de la respuesta de Eli Levine aquí hay una solución más genérica:
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);
}
}
Entonces puedes usarlo con los adaptadores de matriz de Hamcrest así:
verify(a).b(VarArgMatcher.varArgThat(
org.hamcrest.collection.IsArrayContaining.hasItemInArray("Test")));
(Obviamente, las importaciones estáticas lo harán más legible).
También puedes recorrer los argumentos:
Object[] args = invocation.getArguments();
for( int argNo = 0; argNo < args.length; ++argNo) {
// ... do something with args[argNo]
}
por ejemplo, verifique sus tipos y ejecútelos adecuadamente, agréguelos a una lista o lo que sea.
Una característica algo indocumentada: si desea desarrollar un Matcher personalizado que coincida con los argumentos vararg, necesita que implemente org.mockito.internal.matchers.VarargMatcher
para que funcione correctamente. Es una interfaz de marcador vacía, sin la cual Mockito no comparará correctamente los argumentos al invocar un método con varargs utilizando su Matcher.
Por ejemplo:
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);