Junitライブラリ「Mockito」の@Spyの使い方

mockito

「Mockito」の@Spyの使い方を紹介します。
@Spyは、一度使ったら手放せないくらい、素敵な技です。

junitを実装していて、特定のメソッドだけをモックにしたい。ということは誰もが一度は通る道ではないでしょうか。
例えば、特定のメソッド1つだけが、外部APIに接続したりしていて、テストが非常にやりにくいとか。

@Spyを使ったら、そんな悩みはなくなります。
テストが不可能なメソッドのみをモック化して、他メソッドは通常通りに動作させることができる技が、@Spyです。

[スポンサーリンク]

この章でやること

@Spyの基本的な使い方を紹介します。

テスト対象のクラス

SampleA をテスト対象のクラスにします。
このクラスは6行目と8行目で、SampleC を使っています。

public class SampleA {

    private SampleC sampleC;

    public String createName() {
    	Integer id = sampleC.getId();

    	Integer price = sampleC.getPrice(id);

    	String ret = "id:" + id + " price:" + price;
		return ret;
	}

}

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

public class SampleC {

    public  Integer getId() {
    	    return 1 + 2;
    }

    public  Integer getPrice(Integer id) {
        Integer price = id * 100;
        return price;
    }
}

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

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

    @Spy
    private SampleC sampleCMock = new SampleC();

    @InjectMocks
    private SampleA sampleA = new SampleA();

    @Before
    public void setup() {
    	MockitoAnnotations.initMocks(this);
    }
    
    @Test
    public void testVerify() {
    	
    	// モックを用意する。
    	// getPrice()メソッドのみをモック化します。
    	doReturn(555).when(sampleCMock).getPrice((Integer)anyObject());
    	
    	// テスト対象のクラスを実行します。
    	String ret = sampleA.createName();
    	
    	// 戻り値を確認する。
    	assertEquals("id:3 price:555", ret);
    }
}

解説その1

@Mockと@Spyの違いは、
@Mockは、全てのメソッドがモック化されます。(@Mockの使い方はコチラで解説しています。)
@Spyは、一部のメソッドのみをモック化することができます。

サンプルソースでは、
getPrice()メソッドは、モック化しています。
getId()メソッドは、モック化していません。

解説その2

@Spyを使ううえでの注意点があります。
メソッドをモック化して、戻り値を指定する時の注意点です。
whenメソッドではなく、doReturnを使いましょう。
whenメソッドを使うとjunitがエラーになります。

使用できない:when(sampleBMock.getName.....
使用できる:doReturn(555).when(sampleCMock)....

最後に

@Spyは非常に便利な技です。
一度使えばやみつきになります。
わたしは多用しています。mockitoで一番好きな技です。

junitを作成していて、一部のメソッドがHTTP接続していたりしてテストがやりにくい時は、@Spyを使って回避しましょう!
それでは!