New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Known issue: Spring boot overrides ByteBuddy version as 1.7.11 #80

Open
jillesvangurp opened this Issue May 31, 2018 · 11 comments

Comments

3 participants
@jillesvangurp

jillesvangurp commented May 31, 2018

I'm running mockk:1.8, gradle 4.7, kotlin 1.2.4, java 10, spring boot 2.0.2, lots of other libraries, misc gradle plugins related to spring boot, kotlin, etc.

I successfully converted a simple test to use mockk:

class InTokenServiceTest {

    @MockK
    lateinit var ethConversionRateService: EthConversionRateService

    var inTokenService: InTokenService

    init {
        MockKAnnotations.init(this)

        inTokenService = InTokenService(BigDecimal(0.01), ethConversionRateService)

        every { ethConversionRateService.ethEurRate } returns Optional.of(BigDecimal.TEN)
    }

    @Test
    fun shouldConvertToTokenToEuro() {
        val originalEuro = BigDecimal(100.0)
        val token = inTokenService.euroToInToken(originalEuro)
        // this conversion is not completely clean so comparing the rounded double values
        assertThat(inTokenService.inTokenToEuro(token).toDouble()).isEqualTo(originalEuro.toDouble())
    }

Problem & solution

The test works both in gradle and intellij. However when running in gradle, I get a stacktrace with some apparent null somewhere deep inside mockk. I appears to be non fatal since the test runs and passes. I verified this by intentionally breaking the test, which breaks gradle as well. Intellij runs things without any stacktraces.

Then I noticed gradle doing something funky with the transitive dependency on byte-buddy.

io.mockk:mockk:1.8

     org.jetbrains.kotlin:kotlin-reflect:1.2.41
     io.mockk:mockk-common:1.8
         io.mockk:mockk-dsl:1.8
     io.mockk:mockk-dsl-jvm:1.8
         io.mockk:mockk-dsl:1.8
         org.jetbrains.kotlin:kotlin-reflect:1.2.41
     io.mockk:mockk-agent-jvm:1.8
         io.mockk:mockk-agent-api:1.8
         net.bytebuddy:byte-buddy:1.8.8 ➡ 1.7.11
         org.objenesis:objenesis:2.6
         net.bytebuddy:byte-buddy-agent:1.8.8 ➡ 1.7.11

I forced it to use 1.8.8 and that fixes things:

# adding this fixes the problem
testCompile "net.bytebuddy:byte-buddy:1.8.8"

None of my other dependencies seem to be depending on this. Not sure why gradle pulls in 1.7.11.

Stack trace

// -----------------------[ YOUR STACK STARTS HERE ] -----------------------
18:29:25.293 [Test worker] WARN  i.m.proxy.jvm.MockKInstrumentation - Failed to transform class
    java.lang.IllegalArgumentException: null
        at net.bytebuddy.jar.asm.ClassReader.<init>(ClassReader.java:160)
        at net.bytebuddy.jar.asm.ClassReader.<init>(ClassReader.java:143)
        at net.bytebuddy.dynamic.scaffold.TypeWriter$Default$ForInlining.create(TypeWriter.java:2938)
        at net.bytebuddy.dynamic.scaffold.TypeWriter$Default.make(TypeWriter.java:1633)
        at net.bytebuddy.dynamic.scaffold.inline.RedefinitionDynamicTypeBuilder.make(RedefinitionDynamicTypeBuilder.java:171)
        at net.bytebuddy.dynamic.scaffold.inline.AbstractInliningDynamicTypeBuilder.make(AbstractInliningDynamicTypeBuilder.java:92)
        at net.bytebuddy.dynamic.DynamicType$Builder$AbstractBase.make(DynamicType.java:2639)
        at io.mockk.proxy.jvm.MockKInstrumentation.transform(MockKInstrumentation.java:163)
        at java.instrument/java.lang.instrument.ClassFileTransformer.transform(ClassFileTransformer.java:246)
        at java.instrument/sun.instrument.TransformerManager.transform(TransformerManager.java:188)
        at java.instrument/sun.instrument.InstrumentationImpl.transform(InstrumentationImpl.java:560)
        at java.instrument/sun.instrument.InstrumentationImpl.retransformClasses0(Native Method)
        at java.instrument/sun.instrument.InstrumentationImpl.retransformClasses(InstrumentationImpl.java:164)
        at io.mockk.proxy.jvm.MockKInstrumentation.inject(MockKInstrumentation.java:122)
        at io.mockk.proxy.jvm.JvmMockKProxyMaker.proxy(JvmMockKProxyMaker.java:47)
        at io.mockk.impl.instantiation.JvmMockFactory.newProxy(JvmMockFactory.kt:34)
        at io.mockk.impl.instantiation.AbstractMockFactory.newProxy$default(AbstractMockFactory.kt:27)
        at io.mockk.impl.instantiation.AbstractMockFactory.temporaryMock(AbstractMockFactory.kt:99)
        at io.mockk.impl.recording.states.RecordingState$call$retValue$1.invoke(RecordingState.kt:67)
        at io.mockk.impl.instantiation.JvmAnyValueGenerator$anyValue$1.invoke(JvmAnyValueGenerator.kt:27)
        at io.mockk.impl.instantiation.AnyValueGenerator.anyValue(AnyValueGenerator.kt:27)
        at io.mockk.impl.instantiation.JvmAnyValueGenerator.anyValue(JvmAnyValueGenerator.kt:23)
        at io.mockk.impl.recording.states.RecordingState.call(RecordingState.kt:65)
        at io.mockk.impl.recording.CommonCallRecorder.call(CommonCallRecorder.kt:48)
        at io.mockk.impl.stub.MockKStub.handleInvocation(MockKStub.kt:194)
        at io.mockk.impl.instantiation.JvmMockFactoryHelper$mockHandler$1.invoke(JvmMockFactoryHelper.kt:22)
        at io.mockk.impl.instantiation.JvmMockFactoryHelper$mockHandler$1.invoke(JvmMockFactoryHelper.kt:17)
        at io.mockk.impl.instantiation.JvmMockFactory$sam$io_mockk_agent_MockKInvocationHandler$0.invocation(JvmMockFactory.kt)
        at io.mockk.proxy.jvm.MockKCallProxy.call(MockKCallProxy.java:25)
        at io.mockk.proxy.jvm.JvmMockKProxyDispatcher.handle(JvmMockKProxyDispatcher.java:48)
        at io.mockk.proxy.jvm.MockKProxyInterceptor.intercept(MockKProxyInterceptor.java:28)
        at io.inbot.ethclient.conversionrates.EthConversionRateService$ByteBuddy$EC6z52wQ.getEthEurRate(Unknown Source)
        at io.inbot.ethclient.services.InTokenServiceTest$1.invoke(InTokenServiceTest.kt:27)
        at io.inbot.ethclient.services.InTokenServiceTest$1.invoke(InTokenServiceTest.kt:13)
        at io.mockk.impl.eval.RecordedBlockEvaluator$record$block$1.invoke(RecordedBlockEvaluator.kt:22)
        at io.mockk.impl.recording.JvmAutoHinter.autoHint(JvmAutoHinter.kt:23)
        at io.mockk.impl.eval.RecordedBlockEvaluator.record(RecordedBlockEvaluator.kt:31)
        at io.mockk.impl.eval.EveryBlockEvaluator.every(EveryBlockEvaluator.kt:25)
        at io.inbot.ethclient.services.InTokenServiceTest.<init>(InTokenServiceTest.kt:72)
        at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
        at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
        at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
        at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:488)
        at org.junit.platform.commons.util.ReflectionUtils.newInstance(ReflectionUtils.java:429)
        at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:60)
        at org.junit.jupiter.engine.descriptor.ClassTestDescriptor.instantiateTestClass(ClassTestDescriptor.java:208)
        at org.junit.jupiter.engine.descriptor.ClassTestDescriptor.instantiateAndPostProcessTestInstance(ClassTestDescriptor.java:195)
        at org.junit.jupiter.engine.descriptor.ClassTestDescriptor.lambda$testInstanceProvider$0(ClassTestDescriptor.java:185)
        at org.junit.jupiter.engine.descriptor.ClassTestDescriptor.lambda$testInstanceProvider$1(ClassTestDescriptor.java:189)
        at java.base/java.util.Optional.orElseGet(Optional.java:358)
        at org.junit.jupiter.engine.descriptor.ClassTestDescriptor.lambda$testInstanceProvider$2(ClassTestDescriptor.java:188)
        at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.prepare(TestMethodTestDescriptor.java:81)
        at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.prepare(TestMethodTestDescriptor.java:58)
        at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.prepare(HierarchicalTestExecutor.java:89)
        at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.execute(HierarchicalTestExecutor.java:74)
        at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.lambda$executeRecursively$2(HierarchicalTestExecutor.java:121)
        at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:183)
        at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:177)
        at java.base/java.util.Iterator.forEachRemaining(Iterator.java:133)
        at java.base/java.util.Spliterators$IteratorSpliterator.forEachRemaining(Spliterators.java:1801)
        at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484)
        at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474)
        at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:150)
        at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:173)
        at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
        at java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:497)
        at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.lambda$executeRecursively$3(HierarchicalTestExecutor.java:121)
        at org.junit.platform.engine.support.hierarchical.SingleTestExecutor.executeSafely(SingleTestExecutor.java:66)
        at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.executeRecursively(HierarchicalTestExecutor.java:108)
        at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.execute(HierarchicalTestExecutor.java:79)
        at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.lambda$executeRecursively$2(HierarchicalTestExecutor.java:121)
        at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:183)
        at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:177)
        at java.base/java.util.Iterator.forEachRemaining(Iterator.java:133)
        at java.base/java.util.Spliterators$IteratorSpliterator.forEachRemaining(Spliterators.java:1801)
        at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484)
        at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474)
        at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:150)
        at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:173)
        at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
        at java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:497)
        at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.lambda$executeRecursively$3(HierarchicalTestExecutor.java:121)
        at org.junit.platform.engine.support.hierarchical.SingleTestExecutor.executeSafely(SingleTestExecutor.java:66)
        at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.executeRecursively(HierarchicalTestExecutor.java:108)
        at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.execute(HierarchicalTestExecutor.java:79)
        at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:55)
        at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:43)
        at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:170)
        at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:154)
        at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:90)
        at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.processAllTestClasses(JUnitPlatformTestClassProcessor.java:92)
        at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.access$100(JUnitPlatformTestClassProcessor.java:77)
        at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor.stop(JUnitPlatformTestClassProcessor.java:73)
        at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.stop(SuiteTestClassProcessor.java:61)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:564)
        at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35)
        at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
        at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:32)
        at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:93)
        at com.sun.proxy.$Proxy1.stop(Unknown Source)
        at org.gradle.api.internal.tasks.testing.worker.TestWorker.stop(TestWorker.java:123)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:564)
        at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35)
        at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
        at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:155)
        at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:137)
        at org.gradle.internal.remote.internal.hub.MessageHub$Handler.run(MessageHub.java:404)
        at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:63)
        at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:46)
        at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1135)
        at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
        at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:55)
        at java.base/java.lang.Thread.run(Thread.java:844)
// -----------------------[ YOUR STACK TRACE ENDS HERE ] -----------------------
@oleksiyp

This comment has been minimized.

Collaborator

oleksiyp commented May 31, 2018

ByteBuddy 1.8.8 was needed to fix issues with JDK10.

Such exception, of course, may happen if it is downgraded by gradle. I assume it's because of other dependencies depending old bytebuddy.

Thanks for reporting I'll try to figure out how this can be useful.

@oleksiyp oleksiyp added the bug label May 31, 2018

@oleksiyp

This comment has been minimized.

Collaborator

oleksiyp commented May 31, 2018

After all you can try upgrading to newer versions of mockito and other deps that are dependent from older byte buddy. I believe mockito was at least planning to switch byte buddy to support JDK 10

@jillesvangurp

This comment has been minimized.

jillesvangurp commented Jun 1, 2018

I don't have mockito as a dependency. I checked with gradle htmlDependencyReport. It looks like this is coming in via io.mockk:mockk-agent-jvm. I don't see any other dependencies to this in my dependency graph.

@oleksiyp

This comment has been minimized.

Collaborator

oleksiyp commented Jun 1, 2018

This is quite strange. Why it suggested to downgrade it then?

@jillesvangurp

This comment has been minimized.

jillesvangurp commented Jun 1, 2018

That's the big question.

@jillesvangurp

This comment has been minimized.

jillesvangurp commented Jun 1, 2018

Full list of dependencies; hope this helps:

        // make spring use codahale metrics
        compile "io.dropwizard.metrics:metrics-core:4.0.2"

        compile "org.jetbrains.kotlin:kotlin-reflect:$kotlinVersion"
        compile "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlinVersion"
        compile "io.github.microutils:kotlin-logging:1.5.4"
        compile "com.fasterxml.jackson.core:jackson-annotations:2.9.5"
        compile "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.9.5"
        compile "com.fasterxml.jackson.module:jackson-module-kotlin:2.9.5"
        compile("org.springframework.boot:spring-boot-starter-web")
        // disabling webflux for now, might switch back
        // compile "org.springframework.boot:spring-boot-starter-webflux"

        compile "javax.xml.bind:jaxb-api:2.3.0"
        compile "org.web3j:core:3.4.0"
//        compile "com.amazonaws:aws-java-sdk:1.11.275"
        compile "com.amazonaws:aws-java-sdk-ec2:${awsClientVersion}"
        compile "com.amazonaws:aws-java-sdk-s3:${awsClientVersion}"
        compile "com.amazonaws:aws-java-sdk-ssm:${awsClientVersion}"
        compile "com.amazonaws:aws-java-sdk-sqs:${awsClientVersion}"
        compile "com.amazonaws:aws-java-sdk-sns:${awsClientVersion}"
        compile "com.amazonaws:amazon-sqs-java-messaging-lib:1.0.4"
        // make sure this matches spring boot
        compile "org.springframework:spring-jms:${springVersion}"
        compile "org.apache.activemq:activemq-broker:5.15.4"

        compile "org.mariadb.jdbc:mariadb-java-client:2.2.5"
        compile("org.springframework.boot:spring-boot-starter-data-jpa:${springBootVersion}")
        compile("org.springframework.boot:spring-boot-starter-actuator:${springBootVersion}")
        compile "org.flywaydb:flyway-core:5.1.1"
        compile "org.apache.commons:commons-lang3:3.7"
        compile "io.inbot:inbot-utils:1.28"

        compile "com.auth0:java-jwt:3.3.0"

        compile "com.cwbase:logback-redis-appender:1.1.5"
        compile "net.logstash.logback:logstash-logback-encoder:5.1"
        compile "com.opencsv:opencsv:4.1"
        compile "com.github.alexmojaki:s3-stream-upload:1.0.1"

        testCompile("org.springframework.boot:spring-boot-starter-test") {
            // we use junit 5, not 4
            exclude group: "junit"
            exclude group: "org.mockito" // use mockk
            // keep this crap off our classpath; conflicts with jackson
            exclude group: "com.vaadin.external.google", module: "android-json"
        }
        testCompile "org.junit.jupiter:junit-jupiter-api:${junitVersion}"
        testCompile "org.junit.jupiter:junit-jupiter-engine:${junitVersion}"

        testCompileOnly "org.apiguardian:apiguardian-api:1.0.0"
        // make gradle stop whining about apiguardian https://stackoverflow.com/questions/46702273/warning-unknown-enum-constant-status-stable
        testCompile "io.mockk:mockk:1.8"
        // fixes wrong dependency
        testCompile "net.bytebuddy:byte-buddy:1.8.8"
        testCompile "org.jboss.forge.addon:assertj:3.6.2"
        testCompile("com.h2database:h2:1.4.197")
        // note, known issues with gradle 4.7: https://github.com/kotlintest/kotlintest/issues/336
        testCompile "io.kotlintest:kotlintest-runner-junit5:3.1.4"

and the variables referred:

    ext.kotlinVersion = '1.2.41'
    ext.springBootVersion = '2.0.2.RELEASE'
    ext.springVersion = '5.0.6.RELEASE' // make sure to match spring boot
    ext.junitVersion = '5.2.0'
    ext.awsClientVersion = '1.11.338'
@oleksiyp

This comment has been minimized.

Collaborator

oleksiyp commented Jun 1, 2018

Thanks!

@oleksiyp oleksiyp changed the title from transitive dependency on bytebuddy is wrong to Bug: transitive dependency on bytebuddy is wrong Jun 5, 2018

@mikezx6r

This comment has been minimized.

mikezx6r commented Jun 17, 2018

I would guess you're applying the Spring Boot plugin and using the dependency management plugin. This applies Spring Boot's BOM, and sets the versions from that.

Spring Boot 2.0.3 explicitly sets the ByteBuddy version to 1.7.11. You can see the versions here:
https://docs.spring.io/spring-boot/docs/2.0.3.RELEASE/reference/htmlsingle/#appendix-dependency-versions

Explicitly defining the dependency as you have done, or configuring your dependencyManagement section are a couple ways to do it.

Dependency versions are still a major problem...

@jillesvangurp

This comment has been minimized.

jillesvangurp commented Jun 18, 2018

That explains where the dependency is coming from. For now explicitly managing this is good enough. I'm guessing, spring boot will update their side soon as well.

@oleksiyp oleksiyp changed the title from Bug: transitive dependency on bytebuddy is wrong to Known issue: Spring boot overrides ByteBuddy version as 1.7.11 Jun 30, 2018

@oleksiyp oleksiyp added wontfix and removed bug labels Jun 30, 2018

@mikezx6r

This comment has been minimized.

mikezx6r commented Nov 12, 2018

For anyone finding this, Spring Boot 2.1.0 has byte-buddy 1.9.3 as it's version, so after upgrading, it should not be necessary to manually override anymore.

@oleksiyp

This comment has been minimized.

Collaborator

oleksiyp commented Nov 12, 2018

Thank you for the information

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment