Junitライブラリ「Mockito」の@Mockのnameオプションの使い方

mockito

Junitライブラリ「Mockito」の@Mockのオプション「name」を紹介します。

[スポンサーリンク]

私以前は、「name」オプションを使っていませんでした。
が、ある日突然junitが動かなくなるということがありました。

@Mockを使う時は、「name」オプションの併用をおすすめします。
「name」オプションを使うことで、どのクラスにモックをインジェクションするのかを明確化することが出来ます。
もし「name」オプションを使わなかったら、Mockitoがクラスの型を基に自動的にインジェクションしてくれます。(自動化は危険です。)

この章でやること

@Mockのnameオプションの使い方を紹介します。
今回使用するソースは、@Mockと@InjectMocksの使い方のソースを拡張しています。

テスト対象のクラス

SampleA をテスト対象のクラスにします。
このクラスは、3行目と5行目で、SampleB を2回使っています

public class SampleA {

    private SampleB sampleB1;

    private SampleB sampleB2;

    public String createName() {
    	String ret = sampleB1.getName(1);
    	ret = sampleB2.getName(1);
    	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のテストをします。

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

	@Mock(name="sampleB1")
	private SampleB sampleBMock1;

	@Mock(name="sampleB2")
	private SampleB sampleBMock2;

	@InjectMocks
	private SampleA sampleA = new SampleA();

    @Before
    public void setup() {
    	MockitoAnnotations.initMocks(this);
    }
    
    @Test
    public void testVerify() {
    	
    	// モックを用意する。
    	when(sampleBMock1.getName((Integer)anyObject())).thenReturn("mock");
    	when(sampleBMock2.getName((Integer)anyObject())).thenReturn("mock");

    	// テスト対象のクラスを実行します。
    	String ret = sampleA.createName();
    	
    	// 戻り値を確認する。
    	assertEquals("mock", ret);
    }
}

解説

@Mockと@InjectMocksの使い方のソースでは、SampleBを1回のみ使用しています。
こちらは、モックの指定は、@MockのみでもOKです。
Mockitoが自動的にインジェクションしてくれます。

しかし、今回のテスト対象のクラス(SampleA)では、SampleBを2回使用しています。
これでは、モックの指定で、@Mockのみだと、どのクラスにインジェクションしてよいのかMockitoには判断がつかないため、エラーになってしまいます。
@Mock(name="sampleB1")のように、nameオプションでインジェクション対象のクラスを明示的に指定する必要があります。

最後に

悲しいことに、Junitがある日突然動かなくなる。
経験されたことのある人も多いことかと思います。

わたしもたまにやっては後悔しています。
@Mockのnameオプションをつけることで、リスクを回避しましょう!
それでは!