回答 Vs 然后返回

我正在使用 Mockito 进行以后的服务单元测试。我对什么时候使用 doAnswerthenReturn感到困惑。

有人能详细地帮助我吗? 到目前为止,我已经尝试了与 thenReturn

201127 次浏览

当您在模拟方法调用时知道返回值时,应该使用 thenReturndoReturn。调用模拟方法时返回此定义的值。

设置调用方法时返回的返回值。

@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,例如,当需要基于此方法调用的参数计算返回值时。

如果要使用泛型 Answer来存根 void 方法,请使用 doAnswer()

答案指定执行的操作和与模拟交互时返回的返回值。

@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");
}

如果:

  1. 你用的是模拟,不是间谍
  2. 您正在使用的方法是返回一个值,而不是 void 方法。

让我们嘲笑一下这家书店吧

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

您可以使用 doAnswerthenReturn来存根 getAuthor ()。

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呢? 我可以想到两种用例:

  1. 当您想要“存根”void 方法时。

使用 doResponse,您可以在方法调用时执行一些附加操作。

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. 当您使用 Spy 而不是 Mock 时

当使用 When-then Return on Spy Mockito 时,它会调用 real method,然后停止你的回答。如果您不想调用 real method,这可能会导致问题,如下面的示例所示:

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));

我们可以安全地将它存根。

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));

最简单的答案是:

  • 如果在方法调用中需要一个固定的返回值,那么我们应该使用 然后返回(...)
  • 如果您需要执行某些操作或者需要在运行时计算值,那么我们应该使用 那么回答(...)