我正在使用Mockito进行服务稍后的单元测试。我doAnswer
对何时使用vs 感到困惑thenReturn
。
谁能详细帮助我?到目前为止,我已经尝试过使用thenReturn
。
我正在使用Mockito进行服务稍后的单元测试。我doAnswer
对何时使用vs 感到困惑thenReturn
。
谁能详细帮助我?到目前为止,我已经尝试过使用thenReturn
。
Answers:
在模拟方法调用时,应使用thenReturn
或doReturn
当您知道返回值时。调用模拟方法时,将返回此定义的值。
thenReturn(T value)
设置在调用该方法时要返回的返回值。
@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
当调用模拟方法时,例如,当您需要基于此方法调用的参数计算返回值时,如果需要执行其他操作,则使用。
doAnswer()
当您想用generic对无效方法进行存根时使用Answer
。答案指定执行的操作以及与模拟互动时返回的返回值。
@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 return UUID.randomUUID();
。
Answer
是一个功能接口,因此在Java 8中,您可以将其替换为lambda表达式。如果不够干净,则可以进行其他任何常见的异常重构。
doAnswer
并thenReturn
在以下情况下执行相同的操作:
让我们来模拟这个BookService
public interface BookService {
String getAuthor();
void queryBookTitle(BookServiceCallback callback);
}
您可以使用doAnswer
和存根getAuthor()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();
请注意,使用时doAnswer
,您无法在上传递方法when
。
// Will throw UnfinishedStubbingException
doAnswer(invocation -> "Joshua").when(service.getAuthor());
所以,什么时候用doAnswer
代替thenReturn
?我可以想到两个用例:
使用doAnswer,您可以在方法调用时执行一些附加操作。例如,在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);
当使用when-thenReturn时,Spy Mockito将调用真实方法,然后将您的答案存根。如果您不想像下面的示例那样调用真实方法,则可能会导致问题:
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));
使用doAnswer,我们可以安全地将其存根。
List list = new LinkedList();
List spy = spy(list);
doAnswer(invocation -> "java").when(spy).get(0);
assertEquals("java", spy.get(0));
实际上,如果您不想在方法调用时执行其他操作,则可以使用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;}
我在eclipse中收到一条警告:“答案是原始类型。应该对通用类型Answer <T>的引用进行参数设置”。有没有办法解决这个问题(除了忽略c的警告)?
code = UUID.randomUUID()
,我发现无法使用来实现mockito
。