[java] Mockito : doAnswer 대 thenReturn

나중에 서비스 단위 테스트를 위해 Mockito를 사용하고 있습니다. 언제 doAnswerthenReturn.

누구든지 나를 자세히 도울 수 있습니까? 지금까지 thenReturn.



답변

메서드 호출을 모의 할 때 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으로 void 메서드를 스텁하려는 경우 사용 합니다 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");
}


답변

doAnswer다음과 thenReturn같은 경우 동일한 작업을 수행합니다.

  1. Spy가 아닌 Mock을 사용하고 있습니다.
  2. 스터 빙하는 메서드는 void 메서드가 아닌 값을 반환합니다.

이 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합니까? 두 가지 사용 사례를 생각할 수 있습니다.

  1. void 메서드를 “스텁”하고 싶을 때.

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. Mock 대신 Spy를 사용하는 경우

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


답변