web-dev-qa-db-ja.com

mockitoを使用したネストされたメソッド呼び出しのモック

A、B、C、Dと言う4つのクラスがあり、それぞれが別のクラスのメソッドを呼び出しています。

今私はクラスAをモックしており、mockitoを使用してメソッドをモックしたい

_A a = Mockito.mock(A.class);
_

そして、次のような再帰的なメソッド呼び出しで「foo」を取得したい

a.getB().getC().getD()は_"foo"_を返す必要があります

私は試した

when(a.getB()。getC()。getD())。thenReturn( "foo");

しかし、nullPointerExceptionを取得しました

それから私は試した

doReturn( "foo")。when(a.getB()。getC()。getD());

その後_org.mockito.exceptions.misusing.UnfinishedStubbingException:_を得ました

B、C、Dのオブジェクトを作成できること、あるいは

B b = mock(B.class)またはA.setB(new B())

等々。

しかし、それを一発で行うことはできませんか?任意の助けをいただければ幸いです。

24
Abhijeet

コメントから:

RETURNS_DEEP_STUBSを追加すると、トリックができました。

A a = Mockito.mock(A.class, Mockito.RETURNS_DEEP_STUBS);
45
Abhijeet

Abhijeetによる技術的な答えは技術的には正しいですが、理解することが重要です:notするべきです。

あなたの「生産」コードは重いDemeterの法則に違反しています :クラスAはnot取得する必要があることを知っているべきですCを取得してDを取得するにはB.

それは単に、これらすべてのクラス間のカップリングsuper tightにつながります。良い考えではありません。

その意味で、ここでテストを機能させるために特別なことをする必要があるという事実は、実稼働コードがout of the normalであるということを示すものであることがわかります。

したがって、テスト設定を「修正」する代わりに、実際の問題に対処することを検討してください。そして、それはあなたの生産コードdesignです!

また、レコードの場合:getB()。getC()。getD()は「再帰」呼び出しではありません。それは、メソッド呼び出しの「流fluentな」連鎖のようなものです。そして言ったように:それはnot良いことです。

11
GhostCat

ネストされた各オブジェクトのモックを作成してから、これらの各オブジェクトによって呼び出される個々のメソッドをモックしてみてください。

ターゲットコードが次のような場合:

public Class MyTargetClass {

    public String getMyState(MyClass abc){

       return abc.getCountry().getState();
    }
}

次に、この行をテストするために、次のような個々のネストされたオブジェクトのそれぞれのモックを作成できます。

public Class MyTestCase{

@Mock
private MyTargetClass myTargetClassMock;

@Mock
private MyClass myclassMockObj;

@Mock
private Country countryMockObj;

@Before
public void setUp() throws Exception {
    MockitoAnnotations.initMocks(this);
}

    @Test
    public void test01(){

       when(myclassMockObj.getCountry()).thenReturn(countryMockObj);
       when(countryMockObj.getState()).thenReturn("MY_TEST_STATE");
       Assert.assertEquals("MY_TEST_STATE", myTargetClassMock.getMyState(myclassMockObj));
    }
}
1
Nags