テストにおいて、モックを使うことは必須のテクニックの一つです。
この記事ではJUnit、Mockito、PowerMockなどのライブラリを使いながら、モックを使ってテストを行う方法を説明します。
まずは普通にテストする
テスト対象のコードは以下とします。
public class Sample { public String greeting() { String name = getName(); return "こんにちは、" + name + "さん!"; } public String getName() { return "山本"; } }
まずはモックなどは使わず、greeting()を普通にテストしてみます。
import org.junit.Test; import static org.junit.Assert.assertThat; import static org.hamcrest.Matchers.is; public class SampleTest { @Test public void greetingTest() { Sample sample = new Sample(); assertThat(sample.greeting(), is("こんにちは、山本さん!")); } }
テスト対象のコードの一部のpublicメソッドをモック化する場合
テストコードのgetName()が、例えばデータベースに接続してあれこれして返す、みたいな処理だとします。
public class Sample { public String greeting() { String name = getName(); return "こんにちは、" + name + "さん!"; } public String getName() { // DBに接続し、あれこれ処理をして、Stringを返す処理が記述されているとします。 } }
そうした場合、greeting()をテストしたい場合、getName()メソッドをモック化する必要があります。
その場合、テストコードは以下のようになります。
import org.junit.Test; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.doReturn; import static org.junit.Assert.assertThat; import static org.hamcrest.Matchers.is; public class SampleTest { @Test public void greetingTest() { Sample sampleMock = spy(new Sample()); doReturn("田中").when(sampleMock).getName(); assertThat(sampleMock.greeting(), is("こんにちは、田中さん!")); } }
spy()を使うことで、Sampleクラスのインスタンスをモック化しています。
なお
Sample sampleMock = mock(Sample.class);
ではなく
Sample sampleMock = spy(new Sample());
としているのは、mock()を使う場合には、呼び出されるすべての関数の挙動を記述する必要があるためです。
今回はSampleクラスに関してgetName()の挙動はモック化しつつ、greeting()関数はそのまま使いたかったので、spy()を使っています。
テスト対象のコードの一部のprivateメソッドをモック化する場合
テスト対象のコードが以下のようだった場合を考えます。
public class Sample { public String greeting() { String name = getName(); return "こんにちは、" + name + "さん!"; } private String getName() { // DBに接続し、あれこれ処理をして、Stringを返す処理が記述されているとします。 } }
先ほどと同じく、greeting()のテストをしたいときに、getName()をモック化する必要があります。
しかし、getName()が先ほどのようにpublicでなくprivateであれば、方法が変わってきます。
この場合、powerMockというモジュールが重宝します。
import org.junit.Test; import static org.mockito.Mockito.spy; import static org.powermock.api.mockito.PowerMockito.when; import static org.junit.Assert.assertThat; import static org.hamcrest.Matchers.is; public class SampleTest { @Test public void greetingTest() throws Exception{ Sample sampleMock = spy(new Sample()); when(sampleMock, "getName").thenReturn("鈴木"); assertThat(sampleMock.greeting(), is("こんにちは、鈴木さん!")); } }
なお、上記のコードではMockitoではなくPowerMockitoのwhen()を使っている点に注意が必要です。
when(モック化したインスタンス名, メソッド名, 引数).thenReturn("返り値")
とすることで、privateメソッドもモック化することができます。
補足 pom.xmlの記述
今回ご紹介したライブラリを使うにあたっては、pom.xmlまたはbuild.gradleでの記述が必要です。
私が使用したpom.xmlの<dependencies>部分は以下の通りです。
<dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> </dependency> <dependency> <groupId>org.hamcrest</groupId> <artifactId>hamcrest-library</artifactId> <version>1.3</version> </dependency> <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-core</artifactId> <version>2.8.9</version> </dependency> <dependency> <groupId>org.powermock</groupId> <artifactId>powermock-api-mockito2</artifactId> <version>2.0.2</version> <scope>test</scope> </dependency> </dependencies>
なおorg.mockito と org.powermock のバージョンはそれぞれ互換性がないものがあるので、注意してください。