Как протестировать ClassFileTransformer/javaagent?

Я реализовал ClassFileTransformer для javaagent, используя ASM. Поскольку в нем есть ошибки, я хочу написать для него тестовый пример 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 использовать мою измененную версию? Или я что-то совсем упускаю?


person roesslerj    schedule 05.07.2011    source источник


Ответы (1)


Я понял. Нужно реализовать собственный ClassLoader, который выполняет то же преобразование с испытуемым, что и ClassFileTransformer (например, вызывает его). И, конечно же, предметный класс может быть еще не загружен, поэтому его прямое использование может отсутствовать. Поэтому я использовал API отражения Java для выполнения методов предметного класса.

В отдельном файле:

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());
}
person roesslerj    schedule 07.07.2011