JUnitでprivate/protectedメソッドにアクセスするメモ


JUnitに限った話では無いですが、外部からリフレクションを使ってprivateメソッドにアクセスするメモです。

※ソースコードはJUnit4の例です。

privateメソッドにアクセス

テスト対象

まず、適当にテスト対象のクラスを作ってみます。

package dammy;

public class Main {
    //プライベートフィールド
    private String name;

    //初期化
    Main(){
        name = "プライベート";
    }
    //プライベートメソッド
    private int privateMethod(int in){
        return in * 2;
    }
    //プロテクテッド
    protected int protectedMethod(int in){
        return in * 3;
    }
    //パブリック
    public int publicMethod(int in){
        return in * 4;
    }
}

処理としては何も意味なしなので気にしないでください。

リフレクションでアクセス

public class MainTest {
    private Main obj;

    @Before
    public void setUp() throws Exception {
        obj = new Main();
    }

    @After
    public void tearDown() throws Exception {
        obj = null;
    }

    //日本語でメソッド名書くとわかりやすい
    @Test
    public void プライベート変数を参照() throws Exception{
        //名前を指定して取得
        Field field = Main.class.getDeclaredField("name");
        //アクセス権限を与える
        field.setAccessible(true);
        //指定のインスタンス内のfieldを取得
        assertEquals("プライベート", (String)field.get(obj));
    }

    @Test
    public void プライベートメソッドを実行() throws Exception {
        //名前と引数を指定して取得
        Method method = Main.class.getDeclaredMethod("privateMethod", int.class);
        method.setAccessible(true);
        assertEquals(2,method.invoke(obj, 1));
    }

}
  1. getDeclaredField()/Method()で取得
  2. setAccessible()でアクセス可能にする
  3. invokeで対象のインスタンス指定して実行

でOKです。

protectedはビルドパスで設定すると楽

テストコードからprotectedなメソッドにアクセスする場合、最も楽なのはテスト対象と同じパッケージに入れることですが、それはそれでソースコード管理が煩雑になります。
テスト用のコードを別ディレクトリ内に作成しておき、ビルドパスの設定でソースコードと一緒に指定しておくことで同一パッケージにあるように扱うことができます。
図はEclipseの例

@Test
public void プロテクテッドメソッド(){
    //直接参照可能
    assertEquals(3, obj.protectedMethod(1));
}