前回は mock() メソッドを使いメソッドの Mock 化を行いました。
www.shookuro.com
今回は mock() と spy() の違いをサンプルコードで確認したいと思います。
バージョン:
Java 11
junit 4.13
mockito 3.3.3
mock() と spy() の違い
mock() はインスタンスの非 static 且つ public のメソッドをすべて Mock 化します。
なので一部のメソッドを実装のまま使いたい場合には適しません。
spy() は明示的に指定したメソッドのみを Mock 化します。
Mock 化しないメソッドは実装通りのふるまいとなります。
サンプルコードで確認
package org.yyama; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; import java.util.ArrayList; import java.util.List; import org.junit.Test; public class TestSample { @Test public void test01() { List<String> mock = mock(List.class); List<String> spy = spy(new ArrayList<>()); mock.add("a"); mock.add("b"); mock.add("c"); spy.add("a"); spy.add("b"); spy.add("c"); System.out.println(mock.size()); // → 0 System.out.println(spy.size()); // → 3 } }
mock() で作ったインスタンスは add メソッドが Mock 化されているので(もちろん size メソッドも Mock 化されています。)、実際には何も処理されません。
spy() で作ったインスタンスは add メソッドが通常通り動作し、3 つの要素が追加されています。
spy で一部のメソッドを Mock 化する
package org.yyama; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.spy; import java.util.ArrayList; import java.util.List; import org.junit.Test; public class TestSample { @Test public void test01() { List<String> spy = spy(new ArrayList<>()); doReturn(1).when(spy).size(); spy.add("a"); spy.add("b"); spy.add("c"); System.out.println(spy.size()); // → 1 System.out.println(spy.get(0)); // → a System.out.println(spy.get(1)); // → b System.out.println(spy.get(2)); // → c } }
変数 spy の要素数は 3 にかかわらず、標準出力に 1 が出力されます。
「doReturn(1).when(spy).size();」で size メソッドを Mock 化し、1 を返すように設定しています。
「doReturn(1).when(spy).size();」の代わりに「when(spy.size()).thenReturn(1);」としても同じ結果が得られます。
次に戻り値のない List#add メソッドを Mock 化してみます。
package org.yyama; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.spy; import java.util.ArrayList; import java.util.List; import org.junit.Test; public class TestSample { @Test public void test01() { List<String> spy = spy(new ArrayList<>()); doNothing().when(spy).add(0, "a"); spy.add(0, "a"); System.out.println(spy.size()); // → 0 // System.out.println(spy.get(0)); // → IndexOutOfBoundsException } }
戻り値のない List#add(int index, E element) を Mock 化し、何も処理をさせないように設定しています。
この場合、add メソッドで "a" をリストに追加しているにも関わらずサイズは 0 のまま、get(0) を呼び出すと例外が発生します。
まとめ
mock() と spy() の違いをサンプルコードで確認して、 spy() を使用したメソッドの Mock 化を行いました。
適材適所で使い分けられるようにしましょう。
本日はこれまで!
JUnit の基本について書いた記事もぜひご覧ください。
www.shookuro.com
JUnit実践入門 ── 体系的に学ぶユニットテストの技法 WEB+DB PRESS plus
- 作者:渡辺 修司
- 発売日: 2018/11/14
- メディア: Kindle版
- 作者:Jeff Langr,Andy Hunt,Dave Thomas
- 発売日: 2015/09/02
- メディア: 単行本(ソフトカバー)