javagradleaspectjfreefair-aspectj

Post-Compile weaving not working to test code


I'm using Gradle 7.4 and applying the io.freefair.aspectj.post-compile-weaving plugin. I want to test my aspect so I wrote a test class including an static inner class which should be advised by my aspect but my aspect does not advise it. I also wrote another class which should be advised in src/main/java directory and my aspect properly advise it.

For example I have following aspect, classes and tests in package com.example.

@Aspect
public class MyAspect {
  @AfterReturning("@within(com.example.ShouldBeWoven) && execution(* .new(..))")
  public void myAdvice(JoinPoint joinPoint) {
    System.out.println("******* MyAspect advised: " + joinPoint.getSignature().getDeclaringTypeName());
  }
}
@Documented
@Target({TYPE})
@Retention(RUNTIME)
public @interface ShouldBeWoven {
}
class MyClass {

  @ShouldBeWoven
  static class WovenClassInMain {
  }

}
class MyAspectTest {

  @ShouldBeWoven
  static class WovenClassInTest {
  }

  @Test
  void instantiateWovenClassInMain() {
    new WovenClassInMain();
  }
  
  @Test
  void instantiateWovenClassInTest() {
    new WovenClassInTest();
  }

}

The result was that instantiateWovenClassInMain showed message in the advice and instantiateWovenClassInTest did not. How can I weave my aspects to classes in src/test/java directory?

I could achieve this when I was using Load Time Weaving by the way.

Here is an MCVE.


Solution

  • You need to add this to your Gradle build config:

    compileTestJava.ajc.options.aspectpath.from sourceSets.main.output 
    

    See also here.

    I tried with your sample project, and it works for me with these properties set:

    compileJava.ajc.options.compilerArgs << "-showWeaveInfo -verbose"
    compileTestJava.ajc.options.compilerArgs << "-showWeaveInfo -verbose"
    compileTestJava.ajc.options.aspectpath.from sourceSets.main.output
    

    I also had to rename your class PluginTest to PostCompileWeavingPluginTest in order to avoid a build error, because the file name was different from the class name.

    The clean test build log now says:

    > Task :clean
    > Task :compileJava
    Join point 'constructor-execution(void com.example.MyClass$WovenClassInMain.<init>())' in Type 'com.example.MyClass$WovenClassInMain' (WovenClassInMain.java:6) advised by afterReturning advice from 'com.example.MyAspect' (MyAspect.class(from MyAspect.java))
        
    (...)
    
    > Task :compileTestJava
    Join point 'constructor-execution(void com.example.MyAspectTest$WovenClassInTest.<init>())' in Type 'com.example.MyAspectTest$WovenClassInTest' (MyAspectTest.java:9) advised by afterReturning advice from 'com.example.MyAspect' (MyAspect.class(from MyAspect.java))
        
    (...)
    
    > Task :test
    ******* MyAspect wove: com.example.MyClass$WovenClassInMain
    ******* MyAspect wove: com.example.MyAspectTest$WovenClassInTest
    root project 'test'