web-dev-qa-db-ja.com

Mockito:doAnswer Vs thenReturn

私はMockitoをサービス後の単体テストに使用しています。 doAnswerthenReturnをいつ使用するか混乱します。

誰かが私を詳しく助けてくれる?これまでのところ、私はthenReturnでそれを試しました。

80
Rajkumar Thambu

メソッド呼び出しをモックするときの戻り値がわかっているときは、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は、モックメソッドが呼び出されたときに追加のアクションを実行する必要がある場合に使用されます。このメソッド呼び出しのパラメータに基づいて戻り値を計算する必要があるとき。

Voidメソッドを汎用のAnswerでスタブする場合はdoAnswer()を使用してください。

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

以下の場合、doAnswerthenReturnは同じことを行います。

  1. あなたはスパイではなくモックを使っています
  2. スタブ化しているメソッドは、voidメソッドではなく値を返します。

このBookServiceをモックしましょう

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

doAnswerおよびthenReturnを使用して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を使うのでしょうか。私は2つのユースケースを考えることができます:

  1. あなたが "スタブ"無効メソッドをしたいとき。

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. あなたがモックの代わりにスパイを使っているとき

Spy Mockitoでwhen-thenReturnを使用すると、実際のメソッドが呼び出されてから回答がスタブされます。このサンプルのように、実際のメソッドを呼び出したくない場合は、これが問題を引き起こす可能性があります。

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