dependency-analysis-gradle-plugin
dependency-analysis-gradle-plugin copied to clipboard
java.lang.NoClassDefFoundError: org/gradle/kotlin/dsl/PluginAwareExtensionsKt when applying plugin to a Project with a sub Project during tests
Build scan link https://scans.gradle.com/s/segppkfrzjmca/
Plugin version 1.29.0
Gradle version 7.6.1 (Same bug exhibits with Gradle 8.0)
JDK version 11.0.16 (Amazon.com Inc. 11.0.16+8-LTS)
Describe the bug
We have tests that build Projects using org.gradle.testfixtures.ProjectBuilder. We apply the com.autonomousapps.dependency-analysis plugin on the Project during our test. If the test Project does not have a sub Project then plugin application works. However, if the test Project does have a sub Project, then a
java.lang.NoClassDefFoundError: org/gradle/kotlin/dsl/PluginAwareExtensionsKt exception is thrown when the com.autonomousapps.subplugin.RootPlugin attempts to conditionallyApplyToSubprojects as shown in the snippet from the stack trace below (The full stack trace can be seen on the build scan here)
Caused by: java.lang.NoClassDefFoundError: org/gradle/kotlin/dsl/PluginAwareExtensionsKt
com.autonomousapps.subplugin.RootPlugin$conditionallyApplyToSubprojects$1.execute(RootPlugin.kt:65) |
com.autonomousapps.subplugin.RootPlugin$conditionallyApplyToSubprojects$1.execute(RootPlugin.kt:63)
To Reproduce Steps to reproduce the behavior:
- Build a
org.gradle.api.Projectusing theorg.gradle.testfixtures.ProjectBuilder - Build a second
org.gradle.api.Projectusing theorg.gradle.testfixtures.ProjectBuildersetting theProjectfrom step 1 as its parent - Apply the
com.autonomousapps.dependency-analysisplugin to the root project
I created a Junit 5 test to help me diagnose and have included it below (note this test fails as the NoClassDefFoundError exception is thrown)
Also note that if we remove the line ProjectBuilder.builder().withParent(rootProject).build(); from the code, then the test passes.
package org.example;
import org.gradle.api.Project;
import org.gradle.testfixtures.ProjectBuilder;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
public class ProjectBuilderTest {
@DisplayName("Ensure that the dependency-analysis plugin can be applied on a textfixtures project with a subproject")
@Test
void canApplyPluginOnProjectWithSubProject() {
Project rootProject = ProjectBuilder.builder().build();
ProjectBuilder.builder().withParent(rootProject).build();
assertDoesNotThrow(() ->
rootProject.getPluginManager().apply("com.autonomousapps.dependency-analysis"));
}
}
Expected behavior
We expect the plugin application to work on a Project containing a sub Project in the same way as it does on a Project without any sub Project.
Additional context I'm not sure that is related, but I noticed this line [Fix] Don't leak Kotlin stdlib from shaded dependencies. from the 1.29.0 release notes.
I tested against the previous plugin version, i.e. 1.28.0. On this version, a Kotlin java.lang.NoClassDefFoundError is thrown when we apply the plugin on any Project in our test, i.e. even if the Project does not have any sub Project.
Notice from the stack trace below that for version 1.28.0, the exception was thrown by a call to com.autonomousapps.DependencyAnalysisPlugin.applyForProject as opposed to version 1.29.0 where the exception was thrown by a call to com.autonomousapps.subplugin.RootPlugin$conditionallyApplyToSubprojects
Caused by: java.lang.NoClassDefFoundError: org/gradle/kotlin/dsl/NamedDomainObjectCollectionExtensionsKt
at com.autonomousapps.subplugin.ProjectPlugin.<clinit>(ProjectPlugin.kt:55)
at com.autonomousapps.DependencyAnalysisPlugin.applyForProject(DependencyAnalysisPlugin.kt:83)
at com.autonomousapps.DependencyAnalysisPlugin.apply(DependencyAnalysisPlugin.kt:28)
at com.autonomousapps.DependencyAnalysisPlugin.apply(DependencyAnalysisPlugin.kt:22)
I included this context as it appears that something related was fixed in the 1.29.0 release but that it somehow wasn't fixed for the sub Project case.
Thanks for the issue. Looks like some kind of classpath issue. It reminds me of a case in a real (non-test) project that uses Kotlin but wasn't applying any Kotlin plugin to the root project. I am not entirely sure how the classpath works in the context of a unit test like you have, but as I stare at the error and the build scan you shared, it occurs to me that my plugin uses Kotlin DSL, and that missing class is from the Kotlin DSL -- that is, the Gradle jar itself. Maybe try adding testRuntimeOnly(gradleApi()) to your build script. That may not work though because I'm not certain that dependencies also contains the Kotlin DSL classes. My IDE tells me that class comes from gradle-kotlin-dsl-8.5.jar.
More generally, I'm not sure it makes a lot of sense to try to unit test this. I recommend writing functional tests instead. I have a plugin and companion libraries for that here if you're interested.