これだけDIコンテナ全盛期だと、Mockフレームワークは
EasyMockで間に合うでしょう。
ですが、依存するクラスのインスタンスをnewしちゃってるような場合は
EasyMockではちょっと難しい。
で、そこでJMockitの登場になります。
バイトコードレベルでMockオブジェクトに入れ替えるので
newしててもおかまいなし。
JVMの引数に追加しなきゃいけないので、
antやmavenを使うときに気をつけなければならないのですが、
かなり強力なMockフレームワークです。
JUnitのサンプルコードは以下のようになります。
public class JMockitAnnotationsExampleTest { @Test public void testDoOperationAbc() { Mockit.setUpMocks(MockDependencyXyz.class); Object result = new ServiceAbc().doOperation("test"); assertNotNull(result); } @MockClass(realClass = DependencyXyz.class) public static class MockDependencyXyz { @Mock public Object doSomething(String value) { return new Object(); } } }
ServiceAbc#doOperationにて、
DependencyXyzオブジェクトをnewして
DependencyXyz#doSomethingを呼び出す処理を記述しているのですが、
このテストクラス上では、DependencyXyz#doSomethingをMockします。
さらにJMockitではEasyMockのように、記録/再生モードのように
Mockオブジェクトの振る舞いを記述することもできます。
public class JMockitExpectationsExampleTest { @Test public void testDoOperationAbc() { new Expectations(true) { @MockField(methods={"doSomething"}) DependencyXyz mock; { mock.doSomething("test"); returns(new Object()); } }; Object result = new ServiceAbc().doOperation("test"); assertNotNull(result); } }
new Expectations(true)
の中に、Mockオブジェクトの振る舞いを記述します。
インナークラスを書かなくて良いのでものすごく楽です。
ですが、メソッドの処理をMockするだけでなく
コンストラクタの処理をMockすることも考えられます。
最初のケースでは、publicでstaticな
MockDependencyXyz
のコンストラクタを定義すれば、コンストラクタもMock処理になります。
ですが、Expectationsを使用したケースだと、コンストラクタの処理は
実クラスの処理が呼ばれてしまいます。あれー?
どうすれば良いんだろう?
誰か知ってたらご教示下さい。