I am using Invesdwin (https://github.com/subes/invesdwin-instrument) to dynamically load java agents into my Spring Boot project in the main method, before the context starts :
DynamicInstrumentationLoader.waitForInitialized();
DynamicInstrumentationLoader.initLoadTimeWeavingContext();
ApplicationContext springContext = SpringApplication.run(Some_Service.class);
...
This works great because it eliminates the need for adding -javaagent parameters when running the java -jar command from the command line.
The issue arises when it comes to unit tests. Since they don't have a main method (that I can tap into that is), I cannot make those 2 lines run before the Spring Context initializes. Without those arguments, each test will cause the context to fail to load with this error :
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
I can work around this during the final build by setting up the Surefire plugin this way in my 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>
Unfortunately this only works during the final build phase. Running an individual test method in Eclipse will fail unless I manually add those arguments into the run configuration for that test which is a pain to say the least.
I made a custom runner class in an attempt to make code run before the Spring context initializes, like so :
public class WeavingRunner extends SpringJUnit4ClassRunner
{
public WeavingRunner(Class<?> clazz) throws InitializationError
{
super(clazz);
DynamicInstrumentationLoader.waitForInitialized();
DynamicInstrumentationLoader.initLoadTimeWeavingContext();
}
}
Although the Eclipse console does give me hints that the weaving is happening when my base test uses this runner class instead of SpringRunner, I get all sorts of weaving errors that seem to indicate the dynamic weaving hasn't happened soon enough :
java.lang.NoSuchMethodException: com.something.SomeAspectClass.aspectOf()
Is there a known way to replicate code running in a main method when running JUnit tests?
******EDIT******
I noticed something extremely weird with this. If I run the package enclosing the tests as a JUnit test, it works! The above weaving errors only appear when running the src/test/java folder as a JUnit test in Eclipse or running the app itself as a JUnit test (which I ultimately need). The dynamic weaving is working but somehow something is making it only work when running individual tests or up to the enclosing package as a JUnit test. I hope that makes sense!
I was starting to suspect issues with my aop.xml file but how could that be the issue if running individual tests and even entire packages works fine?!