【Android Studio】MockitoのthenAnswerの使い方【日本語】

Android Studio(JAVA)のJUnitで、Mockを使ったテストをしてみた。

そこで、MockitoのthenAnswerの使い方がわからなかったので整理してみた。

初心者の自分でも後から見返してわかるレベルで簡潔に記載。

 

他のプログラミングに関する記事はこちら

スポンサーリンク


 

【そもそもthenAnswerとは何か】

モック化したオブジェクトに対し、スタブを1つ1つ設定していけば返り値は設定できるけどパターンが多くて面倒!

そんなことより、モック化したオブジェクトが持つスタブが受け取った引数によって返り値を決めること出来ないの!?

……という時に使うのがthenAnswer。

 

例えば、以下のようなmethodを持つSubSampleクラスがあったとする。

内容としては、「テストしたくない部分」の処理をした後に、最終的に「引数*2」のintを返すだけのもの。

public class SubSample {
    public int method(int i){
        int result;
        
        // テストしたくない部分
        
        result = i * 2;
        return i;
    }
}

 

「テストしたくない部分」があるためスタブ化し、任意の返り値だけが返ってくるようにしたい場合……。

もし、実際に渡される引数の値が1~5までと決まっていれば以下のような記述でいけなくもないが、

// mockSubSampleがSubSampleクラスのモックオブジェクト
Mockito.when(mockSubSample.method(1)).thenReturn(2);
Mockito.when(mockSubSample.method(2)).thenReturn(4);
Mockito.when(mockSubSample.method(3)).thenReturn(6);
Mockito.when(mockSubSample.method(4)).thenReturn(8);
Mockito.when(mockSubSample.method(5)).thenReturn(10);

 

もし、実際に渡される引数の値が1~1000までとなる場合、上記のような記述では厳しい。

そういう場合にthenAnswerを使う。

 

【早速使う】

thenAnswerの記述は以下の通り。

        Mockito.when([モックオブジェクト].[スタブ化するメソッド]).thenAnswer(new Answer(){
            @Override
            public [返り値の型] answer(InvocationOnMock invocation) throws Exception{
                
                // スタブ化した場合の処理内容
                
                return [返す値];
            }
        });

 

スタブ化した場合の処理内容で、引数を取得する記述は以下の通り。

// 予め○番目の引数を取得するか決めてある場合
[引数の型] [任意の変数名] = invocation.getArgument([何番目の引数を取得するか?], [引数の型]);

// 一旦引数をすべて取得し、そのあとから何番目の引数の値を取得するか決める場合
Object[] args = invocation.getArguments():
[引数の型] [任意の変数名] = ([引数の型]) args[[何番目の引数を取得するか?]];

 

【使用例】

実際に使った例を記載しておく。

 

まず、テスト対象のクラス「Sample」は以下の通り。

SubSampleクラスのmethod(int)を使った値を返す。

テスト対象のSampleクラス

public class Sample {

    private SubSample mSubSample = new SubSample();

    public int returnSubSampleMethod(){
        int i = this.mSubSample.method(1);
        return i;
    }
}

 

次に、テスト対象のクラス「Sample」で使う「SubSample」クラス。

このSubSampleクラスをモック化し、method(int)の内容をthenAnswerを使ったスタブに置き換える。

スタブ化するので処理内容に意味はないが、とりあえず引数*2を返すだけのメソッド。

モック化するSubSampleクラス

public class SubSample {
    public int method(int i){
        int result;
        result = i * 2;
        return result;
    }
}

 

で、これがテストコードのサンプル。

わかりやすいように、SubSampleクラスのmethod(int)の処理を、引数*2ではなく引数*3を返すように設定している。

テストコードSampleTestクラス

public class SampleTest {
    @Mock
    private SubSample mockSubSample;

    @InjectMocks
    private Sample sample;

    @Before
    public void setUp(){
        // 適用
        MockitoAnnotations.initMocks(this);
    }

    @Test
    public void test1(){
        // スタブ作成
        Mockito.when(mockSubSample.method(Mockito.any(Integer.class))).thenAnswer(new Answer(){
            @Override
            public Integer answer(InvocationOnMock invocation) throws Exception{
                int i;
                // getArgumentを使った場合
                i = invocation.getArgument(0, Integer.class);
                i = i * 3;

                // getArgumentsを使った場合
                Object[] args = invocation.getArguments();
                i = (Integer) args[0];
                i = i * 3;
                return i;
            }
        });

        // 実行
        int result = sample.returnSubSampleMethod();

        // 評価
        assertEquals(3,result);
    }
}

 

注意点としては、今回はMockitoでInjectMockしているが、もしPowerMockでInjectしなければならない場合、作成したmockSubSumpleクラス(モックオブジェクト)をwhenNewで注入する必要があること。

あと、thenAnswerの返り値の型に、プリミティブ型(intとか)が設定できないことが挙げられる。と、思う。

 

 

たったこれだけのことを知るのに1日ぐらいかかった……。

もっとこう、どんな初心者が見てもわかるようなMockitoやPowerMockitoの日本語の記事が増えると嬉しいなって思う。

 

他のプログラミングに関する記事はこちら

スポンサーリンク