Junitライブラリ「Mockito」で一部本物のメソッドを使う方法(thenCallRealMethod)

java

「Mockito」でテスト対象のクラスをMock化したけど、一部は本物のメソッドを使いたい。という時に本物メソッドとMockメソッドを分けて使う方法を紹介します。

[スポンサーリンク]

本物メソッドとMockメソッドを分けると聞くと、@Spyを思い浮かべるかと思います。
今回は、@Spyではなく、thenCallRealMethodを使って、実行するメソッドを切り分ける方法を紹介します。

@SpyとthenCallRealMethodの違いは、本記事の「解説」に記述します。
@Spyの使い方は、コチラをどうぞ。

この章でやること

thenCallRealMethodを使って、本物メソッドとMockメソッドを分けて使う方法を紹介します。

テスト対象のクラス

SampleA をテスト対象のクラスにします。
このクラスは、SampleB を使っています。

public class SampleA {

    private SampleB sampleB;

    public String createName() {

    	int id = 1;
    	String ret = sampleB.getName(id);

	return ret;
	}

}

こちらが、SampleB のクラスです。

public class SampleB {

	public  String getName(Integer id) {
    	String name = null;
    	if (id == 1) {
    		name = "test1";
    	} else if (id == 2) {
    		name = "test2";
    	} else {
    		name = "other";
    	}
    	return name;
    }
}

Mockitoを使って、SampleAのテストをします。

SampleAがテスト対象のクラスです。
SampleBは、@Mockとして扱っています。

import static org.mockito.Matchers.*;
import static org.mockito.Mockito.*;
public class MockitoSampleTest {

    @Mock(name="sampleB")
    private SampleB sampleBMock;

    @InjectMocks
    private SampleA sampleA = new SampleA();

    @Before
    public void setup() {
    	MockitoAnnotations.initMocks(this);
    }
    
    @Test
    public void testVerify() {
    	
        // sampleBクラスの本物のメソッドを呼び出すように設定します。
        when(sampleBMock.getName((Integer)anyObject())).thenCallRealMethod();
 
        // テスト対象のクラスを実行します。
        String ret = sampleA.createName();
         
        // 戻り値を確認する。
        // sampleBクラスの本物の戻り値が返却されています。
        assertEquals("test1", ret);
    }
}

解説

SampleBは、@Mockとして扱っています。
通常であれば、SampleBの本物メソッドは呼び出されることはありません。

しかし、今回のサンプルソースでは、20行目でSampleBMockでthenCallRealMethod()を使っています。
thenCallRealMethodを使うことによって、本物のメソッドが呼び出されます。

一見すると、@Spyに非常によく似ています。
@SpyとthenCallRealMethodの違いは、
@Spyは通常、本物のメソッドを呼び出します。モックに置き換えたいメソッドのみを指定して置き換えます。
thenCallRealMethodは、thenCallRealMethodを指定することによって初めて本物のメソッドを呼び出します。

最後に

@SpyとthenCallRealMethodの違いは、非常によく似ていて使い分けが難しいように思います。
(なんで2つあるの?って感じに思えます。)

springフレームワークを使っていると、@Spyの方だと上手くテストが出来ませんでした。(インジェクトが上手くいかなかったため。)
その時は、thenCallRealMethodを使って、本物のメソッドを呼び出すことに成功しました。
個人的には、springを使う場合は、thenCallRealMethodを使う方をおススメします。

ちなみに、@Spyの使い方は、コチラをどうぞ。
それでは!