Estou usando o Mockito para teste de unidade posterior do serviço. Estou confuso quando usar doAnswer
vs thenReturn
.
Alguém pode me ajudar em detalhes? Até agora, tentei com thenReturn
.
Estou usando o Mockito para teste de unidade posterior do serviço. Estou confuso quando usar doAnswer
vs thenReturn
.
Alguém pode me ajudar em detalhes? Até agora, tentei com thenReturn
.
Respostas:
Você deve usar thenReturn
ou doReturn
quando souber o valor de retorno no momento em que simular uma chamada de método. Este valor definido é retornado quando você invoca o método simulado.
thenReturn(T value)
Define um valor de retorno a ser retornado quando o método é chamado.
@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
é usado quando você precisa realizar ações adicionais quando um método simulado é invocado, por exemplo, quando você precisa calcular o valor de retorno com base nos parâmetros desta chamada de método.
Use
doAnswer()
quando quiser criar um stub de método void com genéricoAnswer
.A resposta especifica uma ação que é executada e um valor de retorno que é retornado quando você interage com a simulação.
@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
apenas com return UUID.randomUUID();
.
Answer
é uma interface funcional, então com Java 8 você pode substituí-la por uma expressão lambda. Se o não estiver limpo o suficiente, qualquer outra refatoração usual e incomum é possível.
doAnswer
e thenReturn
faça a mesma coisa se:
Vamos zombar deste BookService
public interface BookService {
String getAuthor();
void queryBookTitle(BookServiceCallback callback);
}
Você pode criar um stub getAuthor () usando doAnswer
e 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();
Observe que, ao usar doAnswer
, você não pode passar um método adiante when
.
// Will throw UnfinishedStubbingException
doAnswer(invocation -> "Joshua").when(service.getAuthor());
Então, quando você usaria em doAnswer
vez de thenReturn
? Posso pensar em dois casos de uso:
Usando doAnswer, você pode realizar algumas ações adicionais na chamada do método. Por exemplo, acione um retorno de chamada em 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);
Ao usar when-thenReturn on, o Spy Mockito chamará o método real e, em seguida, esboçará sua resposta. Isso pode causar um problema se você não quiser chamar o método real, como neste exemplo:
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 criar um stub com segurança.
List list = new LinkedList();
List spy = spy(list);
doAnswer(invocation -> "java").when(spy).get(0);
assertEquals("java", spy.get(0));
Na verdade, se você não quiser fazer ações adicionais na invocação do método, você pode apenas 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;}
recebo um aviso no eclipse para "A resposta é um tipo bruto. As referências ao tipo genérico Resposta <T> devem ser parametrizadas". Existe uma maneira de resolver isso (exceto ignorar o aviso ofc)?
code = UUID.randomUUID()
, achei impossível implementar issomockito
.