6

ClassFileTransformer使用 ASM 为 javaagent 实现了一个。因为它有一些bug,所以我想为它写一个JUnit测试用例。我该怎么做呢?

使用我认为的伪代码:

// Have a test class as subject
public static class Subject {
  public void doSomething(){...}
}
// Manually load and transform the subject
...?
// Normally execute some now transformed methods of the subject
new Subject().doSomething();
// Check the result of the call (i.e. whether the correct attached methods were called)
Assert.assertTrue(MyClassFileTransformer.wasCalled());

现在的问题是:我如何手动加载和转换主题并让 JVM/Classloader 使用我操纵的版本?还是我完全错过了什么?

4

1 回答 1

6

我得到了它。需要实现一个自己的,它对ClassLoader测试对象进行与ClassFileTransformer(例如调用它)相同的转换。当然,主题类可能尚未加载,因此可能不会直接使用它。所以我使用Java反射API来执行主题类的方法。

在一个单独的文件中:

public static class Subject {
    public void doSomething(){...}
}

在测试中:

private static class TransformingClassLoader extends ClassLoader {

    private final String className;

    public TransformingClassLoader(String className) {
        super();
        this.className = className;
    }

    @Override
    public Class<?> loadClass(String name) throws ClassNotFoundException {
        if (name.equals(className)) {
            byte[] byteBuffer = instrumentByteCode(fullyQualifiedSubjectClass);
            return defineClass(className, byteBuffer, 0, byteBuffer.length);
        }
        return super.loadClass(name);
    }
}

@Test
public void testSubject(){
    ClassLoader classLoader = new TransformingClassLoader(fullyQualifiedSubjectClass);
    Class<?> subjectClass = classLoader.loadClass(fullyQualifiedSubjectClass);
    Constructor<?> constructor = subjectClass.getConstructor();
    Object subject = constructor.newInstance();
    Method doSomething = subjectClass.getMethod("doSomething");
    doSomething.invoke(subject);
    Assert.assertTrue(MyClassFileTransformer.wasCalled());
}
于 2011-07-07T08:40:29.537 回答