uso - tutorial mockito java
Usando Mockito para simular clases con parĂ¡metros genĂ©ricos (5)
Aquí hay un caso interesante: el método recibe una colección genérica y devuelve una colección genérica del mismo tipo base. Por ejemplo:
Collection<? extends Assertion> map(Collection<? extends Assertion> assertions);
Este método se puede burlar con la combinación de Mockito anyCollectionOf matcher y la Respuesta.
when(mockedObject.map(anyCollectionOf(Assertion.class))).thenAnswer(
new Answer<Collection<Assertion>>() {
@Override
public Collection<Assertion> answer(InvocationOnMock invocation) throws Throwable {
return new ArrayList<Assertion>();
}
});
¿Existe un método limpio de burlarse de una clase con parámetros genéricos? Digamos que tengo que burlarme de una clase Foo<T>
que necesito pasar a un método que espera un Foo<Bar>
. Puedo hacer lo siguiente fácilmente:
Foo mockFoo = mock(Foo.class);
when(mockFoo.getValue).thenReturn(new Bar());
Suponiendo que getValue()
devuelve el tipo genérico T
Pero eso va a tener gatitos cuando más tarde lo pase a un método esperando a Foo<Bar>
. ¿Es el casting el único medio de hacer esto?
Crear un método de utilidad de prueba . Especialmente útil si lo necesitas por más de una vez.
@Test
public void testMyTest() {
// ...
Foo<Bar> mockFooBar = mockFoo();
when(mockFooBar.getValue).thenReturn(new Bar());
Foo<Baz> mockFooBaz = mockFoo();
when(mockFooBaz.getValue).thenReturn(new Baz());
Foo<Qux> mockFooQux = mockFoo();
when(mockFooQux.getValue).thenReturn(new Qux());
// ...
}
@SuppressWarnings("unchecked") // still needed :( but just once :)
private <T> Foo<T> mockFoo() {
return mock(Foo.class);
}
Creo que necesitas lanzarlo, pero no debería ser tan malo:
Foo<Bar> mockFoo = (Foo<Bar>) mock(Foo.class);
when(mockFoo.getValue).thenReturn(new Bar());
Otra forma de evitar esto es usar la anotación @Mock
lugar. No funciona en todos los casos, pero se ve mucho más sexy :)
Aquí hay un ejemplo:
@RunWith(MockitoJUnitRunner.class)
public class FooTests {
@Mock
public Foo<Bar> fooMock;
@Test
public void testFoo() {
when(fooMock.getValue()).thenReturn(new Bar());
}
}
MockitoJUnitRunner
inicializa los campos anotados con @Mock
.
Siempre puede crear una clase / interfaz intermedia que satisfaga el tipo genérico que desea especificar. Por ejemplo, si Foo era una interfaz, podría crear la siguiente interfaz en su clase de prueba.
private interface FooBar extends Foo<Bar>
{
}
En situaciones en las que Foo no es una clase final , puede extender la clase con el siguiente código y hacer lo mismo:
public class FooBar extends Foo<Bar>
{
}
Entonces podrías consumir cualquiera de los ejemplos anteriores con el siguiente código:
Foo<Bar> mockFoo = mock(FooBar.class);
when(mockFoo.getValue()).thenReturn(new Bar());