JavaのリフレクションでprivateなMapの値を変更する
JUnitでのテストの都合でprivateなMapの値を強制的に変更する必要があったので
リフレクションを使って試しに書いてみました。
なお、JDK1.6での記述になります。
import java.lang.reflect.Field; import java.util.Map; public class ForcedValueSetter { private ForcedValueSetter() { // コンストラクタの隠蔽 } public static void setValueToMap(Object target, String fieldName, Object key, Object value) { Class<?> refClass = target.getClass(); try { Field field = refClass.getDeclaredField(fieldName); field.setAccessible(true); try { @SuppressWarnings("unchecked") Map<Object, Object> map = (Map<Object, Object>)field.get(target); map.put(key, value); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } } catch (SecurityException e) { e.printStackTrace(); } catch (NoSuchFieldException e) { e.printStackTrace(); } } }
以下のようなサンプルクラスでテストを行っています。
import java.util.*; public class MapHolder { private Map<String, String> map = new HashMap<String, String>(); private String[][] values = { { "1", "a" }, { "2", "b" }, { "3", "c" } }; public MapHolder() { for (String[] each : values) { map.put(each[0], each[1]); } } public String get(String key) { return map.get(key); } }
import org.junit.Test; import static org.junit.Assert.*; import static org.hamcrest.core.Is.*; public class ForcedValueSetterTest { @Test public void get() { final MapHolder target = new MapHolder(); ForcedValueSetter.setValueToMap(target, "map", "1", "A"); ForcedValueSetter.setValueToMap(target, "map", "2", "B"); ForcedValueSetter.setValueToMap(target, "map", "3", "C"); ForcedValueSetter.setValueToMap(target, "map", "4", "D"); assertThat(target.get("1"), is("A")); assertThat(target.get("2"), is("B")); assertThat(target.get("3"), is("C")); assertThat(target.get("4"), is("D")); } }