自分の速さで

調べたこと、忘れそうなことをゆるゆると書いていく

static イニシャライザを握りつぶす

はじめに

JUnitでテストコードを書くにあたって、JMockitを使用して適宜モック化してテストを実施していました。 staticイニシャライザにテストとは関係ないコードがあったので実行しないようにモック化したかったのですが、JMockitによるモック化はできなそうだったのでJavassistを使用して解決することにしました。

解決方法

CtClassからstaticイニシャライザオブジェクトを取得できるので、setBodyメソッドを実行してメソッドの中身を書き換えればOK

Javassistそのものの説明は省きます

Hoge.java

package cpp0302.test;

/** モック化対象のクラス */
public class Hoge {

    private static int count;

    static {
        // 検証用に無理やり例外を発生させる
        count = 1 / 0;
    }

    public static void printCount() {
        System.out.println("count: " + count);
    }
}


CrushStaticInitializer.java

package cpp0302.test;

import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtConstructor;

public class CrushStaticInitializer {

    public static void main(String[] args) throws Exception {

        ClassPool cp = ClassPool.getDefault();
        cp.appendSystemPath();

        CtClass hogeClass = cp.get("cpp0302.test.crush.Hoge");
        CtConstructor classInitializer = hogeClass.getClassInitializer();

        // staticイニシャライザの内容を変更
        classInitializer.setBody("{ count = 78; System.out.println(\"staticイニシャライザを握りつぶした\"); }");

        hogeClass.toClass();

        // クラスメソッド実行前にstaticイニシャライザが実行される
        Hoge.printCount();
    }

}


実行結果

staticイニシャライザを握りつぶした
count: 78

これでテストコード実行に関係ない処理を握りつぶすことができました