jMockitで依存クラスをモックオブジェクトに差し替える


これまでモックオブジェクトを作成する EasyMock や jMock を見てきました。
モックオブジェクトをパラメータとしてテスト対象に渡せる場合は、問題ないのですが、テスト対象のクラスの中で new されていると、一気にテストは困難になります。

jMockit は 実行時にクラスをモックオブジェクトへ差し替える機能を提供するツールです。
バイトコード操作の為のJVMへのコマンドライン引数、 -javaagent を用いてクラスの差し替えを行います。

Eclipseの場合はJREの設定を変える必要があります。JVMの引数に -javaagent:jmockit.jar を追加します。
設定自体は簡単なのですが、この点が壁になるかもしれません。

テスト対象は以下の通りです。MockSampleクラスのコンストラクタでサービスクラスを初期化しています。
この様に、テスト対象のクラス内で new されたクラスはモックオブジェクトを適用するのが困難です。
jMockitはこういったクラスをモックオブジェクトに差し替える機能を提供しています。
 public class MockSample {
     private ServiceImpl serviceImpl;
     public MockSample() {
         this.serviceImpl = new ServiceImpl();
     }

     public String execute() {
         return serviceImpl.echo();
     }

     public static class ServiceImpl {
         public String echo() {
             return "hoge";
         }
     }
 }
テストクラスは以下の通りです。差し替えられたMockServiceImplが実行されます。
 import mockit.Mockit;
 import org.testng.annotations.Test;
 import test.MockSample.ServiceImpl;
 import static org.testng.Assert.*;

 public class TestJMockitSample {
     @Test public void jmockTest() {
               // クラスの差し替え
         Mockit.redefineMethods(ServiceImpl.class, MockServiceImpl.class);
         MockSample sample = new MockSample();
         assertEquals(sample.execute(), "Mocked!!!");
     }
     public static class MockServiceImpl {
         public String echo() {
             return "Mocked!!!";
         }
     }
 }
コードはかなり簡単ですね。
JVMの引数をいじるため、Eclipseを設定したり、Mavenを使っている場合も一工夫がいる点が面倒ですが、
一度設定してしまえばかなり完結にテストをかける強力なツールです。

Comment