Как динамически тестировать инструменты JUnit? - PullRequest
0 голосов
/ 03 марта 2020

Я использую Invesdwin (https://github.com/subes/invesdwin-instrument) для динамической загрузки java агентов в мой проект Spring Boot в основном методе до запуска контекста:

DynamicInstrumentationLoader.waitForInitialized();
DynamicInstrumentationLoader.initLoadTimeWeavingContext();

ApplicationContext springContext = SpringApplication.run(Some_Service.class);
...

Это отлично работает, поскольку устраняет необходимость добавления параметров -javaagent при запуске команды java -jar из командной строки.

Проблема возникает, когда дело доходит до юнит-тестов. Поскольку у них нет основного метода (который я могу использовать), я не могу заставить эти две строки работать до инициализации Spring Context. Без этих аргументов каждый тест приведет к невозможности загрузки контекста с этой ошибкой:

ClassLoader [jdk.internal.loader.ClassLoaders$AppClassLoader] does NOT provide an 'addTransformer(ClassFileTransformer)' method. Specify a custom LoadTimeWeaver or start your Java virtual machine with Spring's agent: -javaagent:spring-instrument-{version}.jar

Я могу обойти это во время окончательной сборки, настроив плагин Surefire таким образом в моем POM:

<!--Maven Surefire Plugin-->
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-plugin</artifactId>
            <executions>
                <execution>
                    <goals>
                        <goal>test</goal>
                    </goals>
                </execution>
            </executions>
            <configuration>
                <argLine>
                    -javaagent:lib/aspectjweaver-1.9.5.jar 
                    -javaagent:lib/spring-instrument-5.2.3.RELEASE.jar
                </argLine>
            </configuration>
          </plugin>

К сожалению, это работает только во время финальной фазы сборки. Запуск отдельного метода тестирования в Eclipse завершится неудачей, если я не добавлю эти параметры вручную в конфигурацию запуска для этого теста, что, по меньшей мере, является болью.

Я создал собственный класс runner, пытаясь заставить код выполняться до инициализации контекста Spring, например:

public class WeavingRunner extends SpringJUnit4ClassRunner
{
    public WeavingRunner(Class<?> clazz) throws InitializationError 
    {
        super(clazz);

        DynamicInstrumentationLoader.waitForInitialized();
        DynamicInstrumentationLoader.initLoadTimeWeavingContext();
    }
}

Хотя консоль Eclipse дает мне подсказки о том, что происходит переплетение Когда мой базовый тест использует этот класс бегуна вместо SpringRunner, я получаю всевозможные ошибки ткачества, которые, по-видимому, указывают на то, что динамическое ткачество c произошло не достаточно скоро:

java.lang.NoSuchMethodException: com.something.SomeAspectClass.aspectOf()

Есть ли известный способ реплицировать код, выполняемый в основном методе, при запуске тестов JUnit?

****** РЕДАКТИРОВАТЬ ******

Я заметил нечто чрезвычайно странное с этим. Если я запускаю пакет, содержащий тесты как тест JUnit, это работает! Вышеуказанные ошибки переплетения появляются только при запуске папки src / test / java в качестве теста JUnit в Eclipse или при запуске самого приложения в качестве теста JUnit (который мне в конечном счете необходим). Динамическое плетение c работает, но почему-то что-то заставляет его работать только при выполнении отдельных тестов или до включения пакета в качестве теста JUnit. Я надеюсь, что это имеет смысл!

Я начинал подозревать проблемы с моим файлом aop. xml, но как это могло быть проблемой, если запуск отдельных тестов и даже целых пакетов работает нормально?!

...