new icon example borderfactory java unit-testing generics mockito bounded-wildcard

java - icon - Mockito: Métodos de anulación que devuelven el tipo con Comodines limitados



my icon java (4)

Aunque el método de utilidad propuesto por Marek Radonsky funciona, también hay otra opción que ni siquiera requiere la expresión (insonualmente extraña) de Lambda que sugirió fikovnik:

Como muestra esta respuesta a una pregunta similar, también puede usar lo siguiente:

BDDMockito.willReturn(someList).given(dummyClass).dummyMethod();

Considera este código:

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 } }

El compilador se queja de la línea que está intentando resguardar el comportamiento de dummyMethod() . ¿Alguna sugerencia sobre cómo se usan los métodos de anulación que devuelven un tipo con comodines delimitados?


Golpeé lo mismo ayer. Ambas respuestas de @indescript1 y @millhouse me ayudaron a encontrar una solución alternativa. Casi utilicé el mismo código que @millhouse, excepto que lo hice un poco más genérico, porque mi error no fue causado por un java.util.List , sino por el com.google.common.base.Optional . Mi pequeño método de ayuda, por lo tanto, permite cualquier tipo T y no solo 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; }

Con este método de ayuda podrías escribir:

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

Esto compila muy bien y hace lo mismo que el thenReturn(...) .

¿Alguien sabe si el error que emite el compilador de Java es un error del compilador o si el código es realmente incorrecto?


Supongo que quiere poder cargar algunos someList con algunos valores conocidos; Aquí hay un enfoque que usa Answer<T> junto con un método de ayuda con plantillas para mantener todo seguro para tipos:

@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; }


También puede usar el método no seguro doReturn para este propósito,

@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()); }

como se discussed en el grupo de google de Mockito.

Si bien esto es más simple que thenAnswer , nuevamente tenga en cuenta que no es seguro. Si le preocupa la seguridad del tipo, la answer de Millhouse es correcta.

Detalles adicionales

Para ser claros, aquí está el error de compilación observado,

El método thenReturn (List <capture # 1-of? Extends Number>) en el tipo OngoingStubbing <List <capture # 1-of? extends Number >> no es aplicable para los argumentos (List <capture # 2-of? extends Number>)

Creo que el compilador asignó el primer tipo de comodín durante la llamada de when y luego no puede confirmar que el segundo tipo de comodín en la llamada a continuación es el mismo.

Parece que thenAnswer no se topa con este problema porque acepta un tipo comodín mientras thenReturn toma un tipo no comodín, que debe ser capturado. Desde Mockingbox OngoingStubbing de OngoingStubbing ,

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