【JUnit】 JUnit ~ private 変数 / メソッド をテストするには ~

JUnitについて

 * JUnitプロジェクトの作り方などについては、以下の記事を参照のこと。
https://blogs.yahoo.co.jp/dk521123/6856379.html

■ 解決策

 * Java標準のリフレクション機能を利用する

private 変数

 * java.lang.reflect.Field を使用する

private メソッド

 * java.lang.reflect.Method を使用する

■ サンプル

テスト対象のクラスとメソッド

Sample.java

public class Sample {
  // ★テスト対象:private変数★
  private static String HELLOW = "Hellow, ";

  public String getHellow(String name) {
    return getPrivateHellow(name);
  }

  // ★テスト対象:privateメソッド★
  private String getPrivateHellow(String name) {
    return HELLOW + name;
  }
}

テストクラスとメソッド

SampldTest.java

import java.lang.reflect.Field;
import java.lang.reflect.Method;

import junit.framework.TestCase;

import org.junit.Test;

public class SampleTest extends TestCase {

  // privateメソッドのテスト例
  @Test
  public void testGetPrivateMethodHellow() throws Exception {
    // Methodオブジェクトを取得
    Method method = Sample.class.getDeclaredMethod("getPrivateHellow", String.class);
    // trueをセットすることで、privateメソッドへアクセス可能となります。
    method.setAccessible(true);
    // privateメソッドを実行します。
    Sample sample = new Sample();
    // 第二引数以降が、メソッドの引数です。
    String result = (String) method.invoke(sample, new String("Mike"));
    // 結果確認
    assertEquals("Hellow, Mike", result);
  }
  
  // private変数のテスト例
  @Test
  public void testGetPrivatePropatyHellow() throws Exception {
    // Fieldオブジェクトを取得
    Field field = Sample.class.getDeclaredField("HELLOW");
    // trueをセットすることで、private変数へアクセス可能となります。
    field.setAccessible(true);
    // privateメソッドを実行します。
    Sample sample = new Sample();
    // 第二引数以降が、メソッドの引数です。
    field.set(sample, "Good Afternoon, ");
    // 結果確認
    assertEquals("Good Afternoon, Tom", sample.getHellow("Tom"));
  }
}


■ 補足

finalについて

 * 以下のサイトによると、finalも、今回の方法で対応できそう
http://d.hatena.ne.jp/curest/20080808

定数について

 * 定数(static final)については、今回の方法では不可
  => 以下のサイトにもあるが、確かに今回の方法だと例外が発生する。
http://d.hatena.ne.jp/hidecheck/20090625/1245922555
  => 以下のサイトが役に立つ?
http://stackoverflow.com/questions/9697531/how-to-mock-a-static-final-variable-using-junit-easymock-or-powermock