Mockito:doAnswer Vs然后返回

时间:2016-04-14 06:29:28

标签: java mockito

我正在使用Mockito进行后期单元测试。我很困惑何时使用doAnswer vs thenReturn

任何人都可以详细帮助我吗?到目前为止,我已经使用thenReturn进行了尝试。

3 个答案:

答案 0 :(得分:112)

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

  

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()存根空方法,请使用Answer

     

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

答案 1 :(得分:11)

如果符合以下情况,

doAnswerthenReturn会做同样的事情:

  1. 你正在使用Mock,而不是间谍
  2. 您正在存根的方法是返回一个值,而不是一个void方法。
  3. 让我们嘲笑这个BookService

    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. 当你想要“存根”虚空方法时。
    2. 使用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);
      
      1. 当您使用间谍而不是模拟
      2. 当使用when-thenReturn on 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));
        

答案 2 :(得分:0)

最简单的答案是:

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