#! /bin/blog

実行形式のブログです。というか、ほぼポエムです。

jmockitのDeencapsulationがdeletedされてた

jmockitには、DeencapsulationというマジカルなUtilityクラスがあります。
通常は、アクセスできないフィールドやメソッドにアクセスすることができちゃう禁断のクラスです。
このクラスが、最新のバージョンで削除されていることが発覚しました。

ことの経緯としては、

1. Java 1.6からJava 1.8にVersion Upしたら
2. jmockitが動かない。内部で、JDKのVersionを判定しているようだ。
3. jmockitをVersion Upしたら
4. DeencapsulationがNoClassDef...

となって、まじか.. ぼくの大すきなDeencapsulationが・・・
とっても便利に使っていたのにどうしよぉおおおパキャマラド パキャマラド
パオパオパオパオ パオパオパオパオと考えていたら、
そうだ。似たものをつくって代用しちゃおうということになりました。

package util;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;

import org.apache.commons.lang.reflect.FieldUtils;

/**
 * Reflection Utilities.
 * 
 *
 */
public class ReflectionUtils {
	
    /**
     * デフォルトコンストラクタの禁止.
     */
    private ReflectionUtils() {
    }

    /**
     * 対象のスタティックフィールド変数を指定された値で書き換えます.
     * 
     * @param cls 書き換えたいフィールド変数を持つクラス(スタティック変数の変更. static finalもOK. )
     * @param fieldName フィールド変数名
     * @param value 値
     * @throws NoSuchFieldException
     * @throws SecurityException
     * @throws IllegalArgumentException
     * @throws IllegalAccessException
     */
    public static void writeDeclaredStaticField(@SuppressWarnings("rawtypes") Class cls, String fieldName, Object value) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
        Field field = FieldUtils.getDeclaredField(cls, fieldName, true);
        setFinalStatic(field, value);
    }

    /**
     * 
     * Deencapsulation#setFieldの代用(インスタンス変数の変更。privateもOK.)
     * 
     * 対象インスタンスのフィールド変数を指定された値で書き換えます.
     * 
     * @param cls 書き換えたいフィールド変数を持つクラス
     * @param fieldName フィールド変数名
     * @param value 値
     * @throws IllegalAccessException
     */
    public static void writeField(Object target, String fieldName, Object value) throws IllegalAccessException {
    	FieldUtils.writeField(target, fieldName, value, true);
    }

    private static void setFinalStatic(Field field, Object newValue) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
          field.setAccessible(true);
          Field modifiersField = Field.class.getDeclaredField("modifiers");
          modifiersField.setAccessible(true);
          modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
          field.set(null, newValue);
       }
}


しばらく、javaから離れていたので、トレンドがよくわかりませんが
今、Mockライブラリといえば、PowerMockitoが主流なのでしょうかね。