简体   繁体   中英

ByteBuddy agent test with gradle and JUnit5

I've faced some weird behavior when I try to test my Java Agent written using ByteBuddy

The agent intercepts annotated methods/classes and profile them, nothing complicated

class ByteInstrumentationConfigurer implements BootstrapConfigurer {

    @Override
    void init(...) {
        def instrumentation = ByteBuddyAgent.install()
        new AgentBuilder.Default()
                .type(isAnnotatedWith(TimeProfiling.class))
                .transform((builder, typeDescription, classLoader, module) ->
                        builder.method(not(isAnnotatedWith(Generated))) //ignore groovy generated methods (getMetaClass, etc.)
                            .intercept(MethodDelegation.to(TimeProfilingInterceptor.class)))
                .with(stdoutToLoggerWriter.withTransformationsOnly())
                .installOn(instrumentation) 

And I've got some unit tests where I verify that interceptor method was called

class TimeProfilingInterceptorTest {

    static MockedStatic<TimeProfilingInterceptor> timeProfilingInterceptorMockedStatic

    static {
        //agent installation happens here
        new ByteInstrumentationConfigurer().init([:], [:])
        timeProfilingInterceptorMockedStatic = mockStatic(TimeProfilingInterceptor, CALLS_REAL_METHODS)
    }
    
    @Test
    void profilingEnabledClassLevelTest() {
        //some mocking for my classes here
        testCallingComponent.callClassLevelComponentMethod()
        timeProfilingInterceptorMockedStatic.verify(()->
                TimeProfilingInterceptor.measureAndLogExecutionTime(any(),any(),any()),times(2))
}

And now, when I start this test using from IDEA I see, that 2 my classes were transformed

[Byte Buddy] TRANSFORM com.kmslh.manager.profiling.components.MethodLevelTimeProfilingComponent [sun.misc.Launcher$AppClassLoader@18b4aac2, null, Thread[main,5,main], loaded=false]

[Byte Buddy] TRANSFORM com.kmslh.manager.profiling.components.ClassLevelTimeProfilingComponent [sun.misc.Launcher$AppClassLoader@18b4aac2, null, Thread[main,5,main], loaded=false]

But if I run this tests using gradle test\\build task - no classes transformed. If I output full info - i see that classloader in this case is org.codehaus.groovy.runtime.callsite.CallSiteClassLoader .

[Byte Buddy] DISCOVERY com.kmslh.manager.profiling.components.ClassLevelTimeProfilingComponent$exposedMethod [org.codehaus.groovy.runtime.callsite.CallSiteClassLoader@3b1a332, null, Thread[Test worker,5,main], loaded=false] [Byte Buddy] IGNORE com.kmslh.manager.profiling.components.ClassLevelTimeProfilingComponent$exposedMethod [org.codehaus.groovy.runtime.callsite.CallSiteClassLoader@3b1a332, null, Thread[Test worker,5,main], loaded=false] [Byte Buddy] COMPLETE com.kmslh.manager.profiling.components.ClassLevelTimeProfilingComponent$exposedMethod [org.codehaus.groovy.runtime.callsite.CallSiteClassLoader@3b1a332, null, Thread[Test worker,5,main], loaded=false]

Not sure is it an issue or not, but I'm out of ideas. Also I've tried to rewrite test to Java - no result.

Any suggestions to try?

UPD 1

From what I see - when test started from gradle - no auxiliary classes created

From your log, the Gradle tests run a different class loader than in your example where things work. I assume therefore that your matcher is sensitive to the class loader that is being used. Also, make sure your ignore matcher does not exclude the class loader in the parallel tests.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM