Używam Mockito do późniejszego serwisowania testów jednostkowych. Jestem zdezorientowany, gdy w użyciu doAnswer
vs thenReturn
.
Czy ktoś może mi pomóc szczegółowo? Do tej pory próbowałem tego z thenReturn
.
Używam Mockito do późniejszego serwisowania testów jednostkowych. Jestem zdezorientowany, gdy w użyciu doAnswer
vs thenReturn
.
Czy ktoś może mi pomóc szczegółowo? Do tej pory próbowałem tego z thenReturn
.
Odpowiedzi:
Powinieneś użyć thenReturn
lub, doReturn
gdy znasz wartość zwracaną w momencie mockowania wywołania metody. Ta zdefiniowana wartość jest zwracana po wywołaniu metody mockowanej.
thenReturn(T value)
Ustawia wartość zwracaną, która ma zostać zwrócona po wywołaniu metody.
@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
jest używany, gdy trzeba wykonać dodatkowe akcje przy wywołaniu metody mockowanej, np. gdy trzeba obliczyć wartość zwracaną na podstawie parametrów wywołania tej metody.
Użyj,
doAnswer()
gdy chcesz zablokować metodę void za pomocą genericAnswer
.Odpowiedź określa akcję, która jest wykonywana i wartość zwracaną, która jest zwracana podczas interakcji z makietą.
@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
tylko z return UUID.randomUUID();
.
Answer
to funkcjonalny interfejs, więc w Javie 8 można go zastąpić wyrażeniem lambda. Jeśli nie jest wystarczająco czysty, możliwa jest inna zwykła i nietypowa refaktoryzacja.
doAnswer
i thenReturn
zrób to samo, jeśli:
Kpimy z tego BookService
public interface BookService {
String getAuthor();
void queryBookTitle(BookServiceCallback callback);
}
Możesz odgiąć getAuthor () używając doAnswer
i 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();
Zauważ, że podczas używania doAnswer
nie możesz przekazać metody when
.
// Will throw UnfinishedStubbingException
doAnswer(invocation -> "Joshua").when(service.getAuthor());
Kiedy więc użyjesz doAnswer
zamiast thenReturn
? Przychodzą mi do głowy dwa przypadki użycia:
Używając doAnswer, możesz wykonać dodatkowe czynności przy wywołaniu metody. Na przykład wyzwalaj wywołanie zwrotne w 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);
Podczas korzystania z when-thenReturn on Spy Mockito wywoła prawdziwą metodę, a następnie zgubi twoją odpowiedź. Może to spowodować problem, jeśli nie chcesz wywoływać prawdziwej metody, jak w tym przykładzie:
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));
Używając doAnswer, możemy go bezpiecznie zablokować.
List list = new LinkedList();
List spy = spy(list);
doAnswer(invocation -> "java").when(spy).get(0);
assertEquals("java", spy.get(0));
Właściwie, jeśli nie chcesz wykonywać dodatkowych czynności przy wywołaniu metody, możesz po prostu użyć 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;}
i otrzymuję ostrzeżenie w eclipse o treści „Odpowiedź jest typu surowego. Odniesienia do typu ogólnego Answer <T> powinny być sparametryzowane”. Czy istnieje sposób na rozwiązanie tego problemu (poza ignorowaniem ostrzeżenia o c)?
code = UUID.randomUUID()
mogę tego zaimplementowaćmockito
.