JMockit で java.util.Calendar のメソッドを Mock 化する - kntmr-blog
これの続き。
以下、テスト対象クラスとして単純に文字列を連結して返すだけのクラスを用意。
public class FooService { BarService barService; public String execute(String arg) { return "Foo" + barService.execute(arg); } } public class BarService { public String execute(String arg) { return "Bar" + arg; } }
JMockit の Expectations で Mock 化する
モック化は MockUp<T>
を使う方法以外に、Expectations
を使う方法がある。
FooService#execute(String)
をテストする場合。
public class FooServiceTest { @Tested FooService sut; @Injectable BarService barService; @Test public void test() { final String expected = "FooBARBAZ"; new Expectations() { { barService.execute(anyString); result = "BARBAZ"; times = 1; // モックの挙動と呼出しの検証 } }; String actual = sut.execute("dummy"); assertThat(actual, is(expected)); } }
Expectations
はモックの挙動を定義するだけではなく、メソッド呼出しを検証することができる。
上記は times = 1
で BarService#execute(String)
が1回だけ呼ばれることを検証する。
Verifications
を使うと検証の部分を Expectations
から分離することができる。
public class FooServiceTest { @Tested FooService sut; @Injectable BarService barService; @Test public void test() { final String expected = "FooBARBAZ"; new Expectations() { { barService.execute(anyString); result = "BARBAZ"; // モックの挙動を定義 } }; String actual = sut.execute("dummy"); assertThat(actual, is(expected)); new Verifications() { { barService.execute(anyString); times = 1; // 呼出しの検証 } }; } }
モックに渡した値を検証する場合。
public class FooServiceTest { @Tested FooService sut; @Injectable BarService barService; @Test public void test() { sut.execute("hogehoge"); new Verifications() { { List<String> arg = new ArrayList<String>(); barService.execute(withCapture(arg)); times = 1; assertThat(arg.get(0), is("hogehoge")); } }; } }
withCapture
でモックに渡した値をチェックすることができる。
JMockit で private メソッドを Mock 化する
以下、文字列の連結部分を private メソッドに切り出しただけのクラス。
public class FooService { public String execute(String arg) { return executeInternal(arg); } private String executeInternal(String arg) { return "Foo" + arg; } }
FooService#executeInternal(String)
をテストする場合。
public class FooServiceTest { @Tested FooService sut; @Test public void test() { final String expected = "FooBar"; String actual = Deencapsulation.invoke(sut, "executeInternal", "Bar"); assertThat(actual, is(expected)); } }
Deencapsulation#invoke(Object, String, Object...)
にテスト対象クラスとメソッド名、パラメータを渡して private メソッドを実行する。