Estoy usando Mockito para pruebas unitarias posteriores del servicio. Estoy confundido cuándo utilizar doAnswer
vs thenReturn
.
¿Alguien puede ayudarme en detalle? Hasta ahora, lo he probado con thenReturn
.
Estoy usando Mockito para pruebas unitarias posteriores del servicio. Estoy confundido cuándo utilizar doAnswer
vs thenReturn
.
¿Alguien puede ayudarme en detalle? Hasta ahora, lo he probado con thenReturn
.
Respuestas:
Debe usar thenReturn
o doReturn
cuando conozca el valor de retorno en el momento en que simula una llamada al método. Este valor definido se devuelve cuando invoca el método simulado.
thenReturn(T value)
Establece un valor de retorno que se devolverá cuando se llame al método.
@Test
public void test_return() throws Exception {
Dummy dummy = mock(Dummy.class);
int returnValue = 5;
// choose your preferred way
when(dummy.stringLength("dummy")).thenReturn(returnValue);
doReturn(returnValue).when(dummy).stringLength("dummy");
}
Answer
se utiliza cuando necesita realizar acciones adicionales cuando se invoca un método simulado, por ejemplo, cuando necesita calcular el valor de retorno basado en los parámetros de esta llamada al método.
Úselo
doAnswer()
cuando desee apuntar un método vacío con genéricoAnswer
.Respuesta especifica una acción que se ejecuta y un valor de retorno que se devuelve cuando interactúa con el simulacro.
@Test
public void test_answer() throws Exception {
Dummy dummy = mock(Dummy.class);
Answer<Integer> answer = new Answer<Integer>() {
public Integer answer(InvocationOnMock invocation) throws Throwable {
String string = invocation.getArgumentAt(0, String.class);
return string.length() * 2;
}
};
// choose your preferred way
when(dummy.stringLength("dummy")).thenAnswer(answer);
doAnswer(answer).when(dummy).stringLength("dummy");
}
Answer
just con return UUID.randomUUID();
.
Answer
es una interfaz funcional, por lo que con Java 8 podría reemplazarla con una expresión lambda. Si no está lo suficientemente limpio, es posible realizar otra refactorización habitual e inusual.
doAnswer
y thenReturn
haz lo mismo si:
Vamos a burlarnos de este BookService
public interface BookService {
String getAuthor();
void queryBookTitle(BookServiceCallback callback);
}
Puede stub getAuthor () usando doAnswer
y thenReturn
.
BookService service = mock(BookService.class);
when(service.getAuthor()).thenReturn("Joshua");
// or..
doAnswer(new Answer() {
@Override
public Object answer(InvocationOnMock invocation) throws Throwable {
return "Joshua";
}
}).when(service).getAuthor();
Tenga en cuenta que cuando lo usa doAnswer
, no puede pasar un método when
.
// Will throw UnfinishedStubbingException
doAnswer(invocation -> "Joshua").when(service.getAuthor());
Entonces, ¿cuándo usarías en doAnswer
lugar de thenReturn
? Puedo pensar en dos casos de uso:
Con doAnswer puede realizar algunas acciones adicionales tras la invocación del método. Por ejemplo, active una devolución de llamada en queryBookTitle.
BookServiceCallback callback = new BookServiceCallback() {
@Override
public void onSuccess(String bookTitle) {
assertEquals("Effective Java", bookTitle);
}
};
doAnswer(new Answer() {
@Override
public Object answer(InvocationOnMock invocation) throws Throwable {
BookServiceCallback callback = (BookServiceCallback) invocation.getArguments()[0];
callback.onSuccess("Effective Java");
// return null because queryBookTitle is void
return null;
}
}).when(service).queryBookTitle(callback);
service.queryBookTitle(callback);
Cuando use when-thenReturn on Spy, Mockito llamará al método real y luego eliminará su respuesta. Esto puede causar un problema si no desea llamar al método real, como en este ejemplo:
List list = new LinkedList();
List spy = spy(list);
// Will throw java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
when(spy.get(0)).thenReturn("java");
assertEquals("java", spy.get(0));
Usando doAnswer podemos eliminarlo de forma segura.
List list = new LinkedList();
List spy = spy(list);
doAnswer(invocation -> "java").when(spy).get(0);
assertEquals("java", spy.get(0));
En realidad, si no desea realizar acciones adicionales tras la invocación del método, puede usar doReturn
.
List list = new LinkedList();
List spy = spy(list);
doReturn("java").when(spy).get(0);
assertEquals("java", spy.get(0));
doAnswer(new Answer() { ... return null;}
aparece una advertencia en eclipse para "La respuesta es un tipo sin formato. Las referencias al tipo genérico Respuesta <T> deben parametrizarse". ¿Hay alguna forma de resolver esto (excepto ignorar la advertencia de c)?
code = UUID.randomUUID()
, encontré imposible implementar estomockito
.