Mockito: doAnswer Vs thenReturn

Eu estou usando o Mockito para teste posterior de unidade de serviço. Estou confuso quando usar doAnswer vs thenReturn .

Alguém pode me ajudar em detalhes? Até agora, eu tentei com o thenReturn .

Você deve usar thenReturn ou doReturn quando souber o valor de retorno no momento em que você ignorar uma chamada de método. Esse valor definido é retornado quando você chama o método de simulação.

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 é usada quando você precisa fazer ações adicionais quando um método de simulação é chamado, por exemplo, quando você precisa calcular o valor de retorno com base nos parâmetros dessa chamada de método.

Use doAnswer() quando você quiser stub um método vazio com Answer genérica.

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 answer = new Answer() { 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"); } 

doAnswer e thenReturn fazem a mesma coisa se:

  1. Você está usando Mock, não Spy
  2. O método que você está stubbing está retornando um valor, não um método vazio.

Vamos zombar deste BookService

 public interface BookService { String getAuthor(); void queryBookTitle(BookServiceCallback callback); } 

Você pode 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 sobre when .

 // Will throw UnfinishedStubbingException doAnswer(invocation -> "Joshua").when(service.getAuthor()); 

Então, quando você usaria o doAnswer vez do thenReturn ? Eu posso pensar em dois casos de uso:

  1. Quando você quer “stub” método vazio.

Usando doAnswer você pode fazer algumas ações adicionais sobre a invocação do método. Por exemplo, acione um retorno de chamada no 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); 
  1. Quando você está usando o Spy em vez de Mock

Quando usar when-thenReturn no Spy Mockito irá chamar o método real e, em seguida, stub 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 o doAnswer, podemos colocá-lo em 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 sobre a invocação do método, basta usar o doReturn .

 List list = new LinkedList(); List spy = spy(list); doReturn("java").when(spy).get(0); assertEquals("java", spy.get(0));