Gradle: Gradle Junit 5 tries to ClassLoad invalid anonymous classes generated by the Kotlin Compiler

Created on 3 Apr 2018  路  3Comments  路  Source: gradle/gradle

I haven't tested this with other Java testing frameworks, but this is certainly true with the new Junit Platform test engine.

Expected Behavior

If I have a test like the following, Gradle should be able to have Gradle run it and pass:

package testing

import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.assertAll

class MinimalRequiredCodeTest {

    @Test
    fun simpleExampleCase() {
        val listOfElements = 0..100
        assertAll(listOfElements.map { _ ->
            {
                // This line is really important even though it does nothing.
                listOfElements
                assertEquals("wonderful", "wonderful") {
                    // Its very important that this lambda not use any externally scoped variables
                    "Should have worked"
                }
            }
        })
    }
}

Relevant chunk of build.gradle.kts:

dependencies {
    "compile"(kotlin("stdlib-jdk8", "1.2.30"))
    "testCompile"("org.junit.jupiter:junit-jupiter-api:5.1.0")
    "testRuntime"("org.junit.jupiter:junit-jupiter-engine:5.1.0")
    "testRuntime"(create(group = "org.junit.platform", name = "junit-platform-launcher", version = "1.1.0"))
}

tasks.withType<Test> {
    testLogging {
        events(TestLogEvent.FAILED, TestLogEvent.PASSED, TestLogEvent.SKIPPED, TestLogEvent.STARTED)
        displayGranularity = 0
        showExceptions = true
        showCauses = true
        showStackTraces = true
        exceptionFormat = TestExceptionFormat.FULL
    }
    useJUnitPlatform()
}

tasks.withType<KotlinCompile> {
    kotlinOptions.jvmTarget = "1.8"
}

A reproduction of the bug in repository format can be found linked below.

Current Behavior

Gradle throws an exception about trying and failing to load some anonymous class generated by the compiler.

org.gradle.api.internal.tasks.testing.TestSuiteExecutionException: Could not execute test class 'testing.MinimalRequiredCodeTest$simpleExampleCase$1$1$1'.
    at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.processTestClass(SuiteTestClassProcessor.java:53)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    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.processTestClass(Unknown Source)
    at org.gradle.api.internal.tasks.testing.worker.TestWorker.processTestClass(TestWorker.java:109)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    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:146)
    at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:128)
    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.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:55)
    at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.NoClassDefFoundError: testing/MinimalRequiredCodeTest$simpleExampleCase$1$1
    at java.lang.Class.getEnclosingMethod0(Native Method)
    at java.lang.Class.getEnclosingMethodInfo(Class.java:1072)
    at java.lang.Class.getEnclosingClass(Class.java:1272)
    at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor.isTopClass(JUnitPlatformTestClassProcessor.java:100)
    at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor.access$300(JUnitPlatformTestClassProcessor.java:52)
    at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.execute(JUnitPlatformTestClassProcessor.java:86)
    at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.execute(JUnitPlatformTestClassProcessor.java:80)
    at org.gradle.api.internal.tasks.testing.junit.AbstractJUnitTestClassProcessor.processTestClass(AbstractJUnitTestClassProcessor.java:66)
    at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.processTestClass(SuiteTestClassProcessor.java:51)
    ... 25 more
Caused by: java.lang.ClassNotFoundException: testing.MinimalRequiredCodeTest$simpleExampleCase$1$1
    at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
    ... 34 more

I think the key important line here is Gradle trying to class load classes that it shouldn't be classloading.

Caused by: java.lang.ClassNotFoundException: testing.MinimalRequiredCodeTest$simpleExampleCase$1$1

Context

I was having my intern (@Octogonapus) convert our build from using the Junit 5 supplied Gradle Plugin to using the Junit 5 support that is built into Gradle. This test ran fine under the Junit 5 supplied plugin but breaks under Gradle.

Steps to Reproduce (for bugs)

Run this project:
https://github.com/JLLeitschuh/gradle-classloading-test-bug

Your Environment


Gradle 4.6
------------------------------------------------------------

Build time:   2018-02-28 13:36:36 UTC
Revision:     8fa6ce7945b640e6168488e4417f9bb96e4ab46c

Groovy:       2.4.12
Ant:          Apache Ant(TM) version 1.9.9 compiled on February 2 2017
JVM:          1.8.0_92 (Oracle Corporation 25.92-b14)
OS:           Mac OS X 10.13.3 x86_64

Most helpful comment

Confirmed fixed in 4.7-rc-1. Thanks @mkobit!

All 3 comments

Sounds like pretty much exactly the same bug.
I totally missed when looking for similar issues.

Confirmed fixed in 4.7-rc-1. Thanks @mkobit!

Was this page helpful?
0 / 5 - 0 ratings