web-dev-qa-db-ja.com

mockitoでビルダーをモックする方法

私はビルダーを持っています:

_class Builder{
     private String name;
     private String address;
     public Builder setName(String name){
         this.name = name;
         return this;
    }
     public Builder setAddress(String address){
         this.address = address;
         return this;
    }

}
_

Mockitoでビルダーをモックすると、すべてのメソッドでnullが返されます。したがって、when().thenReturnを使用してすべての関数自体をモックすることなく、すべての関数呼び出しでビルダーに自身を返す簡単な方法があります。

29

RETURN_DEEP_STUBS を使用して、チェーンAPIをモックできます。

ビルダーが呼び出される正確な順序がわかっている場合、これを使用する方法の例を次に示します。

Builder b = Mockito.mock(Builder.class, RETURNS_DEEP_STUBS);
when(b.setName("a name").setAddress("an address")).thenReturn(b);
assert b.setName("a name").setAddress("an address") == b; // this passes

残念ながら、これは「さまざまなビルダーメソッドすべて」を模倣する一般的な方法を提供しないため、常にこれが返されます。必要な場合は、他の回答を参照してください。

10

RETURN_DEEP_STUBSの使用に関する問題は、メソッドを呼び出すたびに異なるモックを取得することです。あなたの質問から、正しい戻り値の型を持つ各メソッドに対して、それが呼び出されたモックを実際に返すデフォルトのAnswerを使用したいと思います。これは次のようになります。私はこれをテストしていないので、タイプミスが含まれている可能性があることに注意してください。ただし、意図が明確であることを願っています。

import static org.mockito.Mockito.RETURNS_DEFAULTS;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;

public class SelfReturningAnswer implements Answer<Object>{

    public Object answer(InvocationOnMock invocation) throws Throwable {
        Object mock = invocation.getMock();
        if( invocation.getMethod().getReturnType().isInstance( mock )){
            return mock;
        }
        else{
            return RETURNS_DEFAULTS.answer(invocation);
        }
    }
}

次に、モックを作成するときに、これをデフォルトの回答として指定します。これにより、モックは可能な各メソッドから自分自身を返すようになります。ただし、モックの戻り値の型が間違っているメソッドを呼び出すと、通常のモックのように動作します。

このようにモックを作成します

Builder mockBuilder = mock( Builder.class, new SelfReturningAnswer());

または、このクラスの定数を作成して、次のように記述します

@Mock( answer = SELF_RETURNING ) private Builder mockBuilder;

お役に立てば幸いです。

41

Mockito 2.0(ベータ版)以降、 _RETURNS_SELF_ に対して David Wallaceの回答 とほぼ同じように動作する新しいデフォルトの回答があります。 Mockitoドキュメントの例:

_@Test
public void use_full_builder_with_terminating_method() {
    HttpBuilder builder = mock(HttpBuilder.class, RETURNS_SELF);
    HttpRequesterWithHeaders requester = new HttpRequesterWithHeaders(builder);
    String response = "StatusCode: 200";

    when(builder.request()).thenReturn(response);

    assertThat(requester.request("URI")).isEqualTo(response);
}
_

MockitoクラスとAnswers enumの両方に表示されるため、@Mock(answer = RETURNS_SELF)構文とも互換性があることに注意してください。

20
Jeff Bowman