【Android Studio】Mockito産のMockがInjectMockが出来ない理由【日本語】

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

が、前記事(こちら)の冒頭で書いた通り、なぜかMockito産のMockがInjectMockがされずに困り果てた。

結局、前記事の通りPowerMockitoを使って解決したのだが、使っている内にInjectMockが効かない理由が判明したのでメモしておく。

 

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

スポンサーリンク


 

【結論】

ざっと結論を言ってしまうと、モック化するオブジェクトを

・コンストラクタ
・セッター
・プロパティ(フィールド)

上記以外のところで作成しているコードの場合、InjectMockが出来ないらしい。

 

【詳細(InjectMockが効かない例)】

以下の場合はInjectMockが効かない。

 

テスト対象のクラス「Sample」

package com.sample.junittest2;

public class Sample {

    public int returnSubSampleMethod(){
        SubSample subSample = new SubSample();
        int i = subSample.method();
        return i;
    }

}

 

テスト対象のクラスで使っているクラス「SubSample」

package com.sample.junittest2;

public class SubSample {
    public int method(){
        return 1;
    }
}

 

テストコード

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()).thenReturn(2);

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

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

 

やってることは以下の通り。

・SampleクラスのreturnSubSampleMethod()をテストする
・returnSubSampleMethod()は、SubSampleのmethod()を使い、固定で1を返す
・SubSampleをモック化し、SubSampleのmethod()の返り値を2に変更する

 

上記の場合、InjectMockが適用されないので失敗に終わる。

その理由は、Sampleクラス内でSubSampleクラスが、テストするメソッド内でインスタンス化しているから。

 

 

【詳細(InjectMockが効く例)】

では、InjectMockが効く場合はどんなものがあるのか、具体例を記載していく。

冒頭に述べた通り、以下3つのいずれかでインスタンス化している場合はInjectMockが効く。

・コンストラクタ
・セッター
・プロパティ(フィールド)

 

なので、Sampleクラスを以下の通り修正するとInjectMockが適用されるようになる。

※テストコードとモック化するクラスは変更する必要なし

 

テスト対象のクラス「Sample」(コンストラクタを使用した場合)

package com.sample.junittest2;

public class Sample {

    private SubSample mSubSample;

    public Sample(){
        this.mSubSample = new SubSample();
    }

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

 

テスト対象のクラス「Sample」(セッターを使用した場合)

package com.sample.junittest2;

public class Sample {

    private SubSample mSubSample;

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

    public void setmSubSample(SubSample subSample){
        this.mSubSample = subSample;
    }
}

 

テスト対象のクラス「Sample」(プロパティ(フィールド)を使用した場合)

package com.sample.junittest2;

public class Sample {

    private SubSample mSubSample = new SubSample();

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

 

 

もし、実コードを変更することが何らかの理由で不可能で、上記理由によりInjectMockが効かない場合、こちらの記事で書いた通りPowerMockitoで解決するしかない気がする。

MockitoとかPowerMockitoに関する記事で、日本語で誰にもわかりやすく書いている記事って少ないような気がする。

 

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

スポンサーリンク