byte-buddy icon indicating copy to clipboard operation
byte-buddy copied to clipboard

How to apply Byte Buddy plugin placed under /src/test?

Open martyn0ff opened this issue 1 year ago • 13 comments

Hey, I wrote a plugin to enhance some of the classes that are used only in tests. The plugin itself is located under /src/test folder. However I am not sure how to correctly configure POM file for this to work in a way I expect (or if this is possible at all). Below is a snippet from build section.

<build>
  ...
 <plugin>
        <groupId>net.bytebuddy</groupId>
        <artifactId>byte-buddy-maven-plugin</artifactId>
        <version>${byte-buddy.version}</version>
        <executions>
          <execution>
            <goals>
              <goal>transform</goal>
            </goals>
          </execution>
        </executions>
        <configuration>
          <execution>
          </execution>
          <transformations>
            <transformation>
              <plugin>
               <!-- Some plugin located in /src/main -->
              </plugin>
            </transformation>
            <transformation>
              <plugin>
               <!-- Some plugin located in /src/test -->
              </plugin>
            </transformation>
          </transformations>
        </configuration>
      </plugin>
...
</build>

Running mvn process-classes results in Maven not being able to resolve the second plugin. I've tried to change the goal from transform to transform-test and running process-test-classes phase instead, but that didn't work too. What can I do about this?

martyn0ff avatar Jan 06 '24 17:01 martyn0ff

What you describe should work. What problem are you encountering when using transform-test?

raphw avatar Jan 09 '24 20:01 raphw

I'm getting the following error when I execute mvn clean process-test-classes: [ERROR] Failed to execute goal net.bytebuddy:byte-buddy-maven-plugin:1.14.5:transform-test (default) on project <project name>: Cannot resolve plugin: <fqpn of a plugin in /src/test> -> [Help 1]

martyn0ff avatar Jan 10 '24 12:01 martyn0ff

Is the plugin included in the plugin's dependencies? It seems like a plugin fails to load. It should be added as a dependency to the plugin itself.

raphw avatar Jan 10 '24 18:01 raphw

@raphw Could you please elaborate? I'm not sure what do you mean.

martyn0ff avatar Jan 10 '24 20:01 martyn0ff

In Maven, are the plugins available using:

<plugin>
  ...
  <dependencies>...</dependencies>
</plugin>

Or how are the plugins added to the build cycle.

raphw avatar Jan 11 '24 21:01 raphw

I add Byte Buddy plugins are into build cycle like so:

<!-- Byte Buddy plugins -->
<plugin>
  <groupId>net.bytebuddy</groupId>
  <artifactId>byte-buddy-maven-plugin</artifactId>
  <version>${byte-buddy.version}</version>
  <executions>
    <execution>
      <goals>
        <goal>transform</goal>
        <goal>transform-test</goal>
      </goals>
    </execution>
  </executions>
  <configuration>
    <execution>
    </execution>
    <transformations>
      <transformation>
        <plugin>
          <!-- fqpn of a plugin in /src/main is here !-->
        </plugin>
      </transformation>
      <transformation>
        <plugin>
         <!-- fqpn of a plugin in /src/test is here !-->
        </plugin>
      </transformation>
    </transformations>
  </configuration>
</plugin>

martyn0ff avatar Jan 12 '24 16:01 martyn0ff

I think you need to define the plugin twice. Once transform for the plugin placed in main, once transform-test for the plugin placed in test. The test scope is not available while the main scope is resolved (and transformed).

raphw avatar Jan 12 '24 21:01 raphw

Unfortunately, I couldn't get it to work either. This is what I came up with:

<build>
<!-- other plugins -->
<!-- Byte Buddy plugins -->
<plugin>
<groupId>net.bytebuddy</groupId>
<artifactId>byte-buddy-maven-plugin</artifactId>
<version>${byte-buddy.version}</version>
<executions>
  <execution>
    <id>main</id>
    <goals>
      <goal>transform</goal>
    </goals>
    <configuration>
      <transformations>
        <transformation>
          <plugin>
            <!-- fqpn of a plugin in /src/main -->
          </plugin>
        </transformation>
      </transformations>
    </configuration>
  </execution>
  <execution>
    <id>test</id>
    <goals>
      <goal>transform-test</goal>
    </goals>
    <phase>process-test-classes</phase>
    <configuration>
      <transformations>
        <transformation>
          <plugin>
            <!-- fqpn of a plugin in /src/test -->
          </plugin>
        </transformation>
      </transformations>
    </configuration>
  </execution>
</executions>
</plugin>
</build>

Am I missing something here? Logically this should work, I'm binding my plugin to process-test-classes phase explicitly, which by then should be able to see all my compiled test classes. I also have tried declaring byte-buddy-maven-plugin twice, each with its own <execution>, but it also fails (not to mention Maven giving a warning about using same plugin twice).

martyn0ff avatar Jan 13 '24 16:01 martyn0ff

That's how I'd do it and it works for me.

Could hou create a minimal reproducer?

raphw avatar Jan 13 '24 21:01 raphw

Sure, here it is: https://github.com/martyn0ff/bytebuddy-reproducer. I'm working with Spring Boot, so this is a minimal Spring Boot project which fails with same error (not sure if it may affect the result somehow).

martyn0ff avatar Jan 16 '24 17:01 martyn0ff

I see now what the issue is. The configuration refers to a Maven Coordinate. You would need to create a "test-jar" and then set:

<packaging>test-jar</packaging>

In the plugin-tag.

An easier option would however be to create a custom Maven module that includes your plugin and then configure it by setting

<artifactId>my-plugin-module</artifactId>

Alternatively, you can also activate class path discovery and load the plugin from a service. This would trigger both plugins during test, though.

raphw avatar Jan 19 '24 12:01 raphw

Thank you Rafael, this had worked very well. However now I am experiencing another issue - a ByteBuddy plugin that I wrote can not see classes that are located in test source folder. The plugin is supposed to scan test classes for annotations, find my custom annotation that takes takes an instance of Class<?> as annotation attribute and perform some logic based on the class passed. If I pass a class that is located in source folder, everything is OK, but with classes from test source folder I am getting TypeNotFoundException.

 Failed to transform class com.acme.foo.TestClass using com.acme.foo.ByteBuddyPlugin8021e26: Type com.acme.foo.Baz not present -> [Help 1]

What can I do about it?

martyn0ff avatar Feb 05 '24 18:02 martyn0ff

Are you still using the transform-test goal? It's resolving the test class path: https://github.com/raphw/byte-buddy/blob/master/byte-buddy-maven-plugin/src/main/java/net/bytebuddy/build/maven/ByteBuddyMojo.java#L668

raphw avatar Feb 05 '24 20:02 raphw