我正在尝试将MAVEN Java项目实验性地移植到gradle。我遇到的一个问题是由于NoSuchMethodError在运行时(执行期间)发生而无法执行单元测试。我正在调用FileUtils.write()
方法。
我修改了我的代码以跟踪加载了FileUtils类的ClassLoader中可用的类路径,我有以下内容:
C:/Sdk/gradle-2-7/lib/commons-io-1.4.jar
C:/Users/<me>/.gradle/caches/modules-2/files-2.1/commons-io/commons-io/2.4/b1b6ea3b7e4aa4f492509a4952029cd8e48019ad/commons-io-2.4.jar
除此之外,我看到在测试运行期间类路径中有2个版本的commons-io,而第一个带有gradle的版本因此具有更高的优先级。
根本原因是什么?如何解决这个问题?
实际上,我希望除了在我的gradle项目的依赖项中显式声明之外,在类路径中没有可用的JAR。
更新:似乎我已经了解了根本原因 - 正在测试的项目是'gradle plugin'并且在gradle中编译它我必须在{{1 }}:
build.gradle
这会将所有gradle依赖项捕获到我的项目中。虽然我仍然没有找到修复它的方法:
dependencies {
compile gradleApi()
}
(请参阅http://gradle.1045684.n5.nabble.com/exclude-some-dependencies-from-gradleApi-dependency-td5712103.html)。答案 0 :(得分:0)
TL; DR
不要使用commons-io:2.1,使用Java8,Groovy,或者使用helper来代替commons-io。
<强> Explination 强>
根本原因是gradleApi()
包含commons-io:1.4并且当测试执行时,你最终在类路径上有两个commons-io jar并且1.4版本恰好更早,以便&#39;为什么你得到NoSuchMethodError
。
这是因为Gradle没有像Maven那样在单独的类加载器中隔离每个插件。鉴于Gradle的工作原理,您无法做到。这是因为在Gradle中,一个好的设计策略是将多个插件链接在一起做一件事。您有一个插件可以将事物配置为通用的,并且没有关于如何使用它的意见。然后你有一个非常固执的插件,用一些假设来配置一个项目。当用户没有与您分享相同的意见时,这很有用,他们可以只应用基本插件并应用他们自己的意见。
更具体的例子是你有一个包含其他插件使用的extension的jar。这可能是&#34; failBuildOnQualityError&#34;。然后,当checkstyle,findbugs,jacoco等发现问题时,每个单独的插件(使用不同的坐标)将尝试使用该扩展来查看它们是否应该使构建失败。
答案 1 :(得分:0)
好的,我最初的诊断“ Gradle没有将插件的类路径与自己的类路径隔离”是错误的。根本原因实际上是......
dependencies {
compile gradleApi()
}
...摄取到许多依赖项(包括commons-io:1.4)。正确的解决方案(至少对我来说可行)只包括明确要求的罐子:
versions = [
gradle: "2.8",
groovy: "2.4.4",
]
dependencies {
compile "org.codehaus.groovy:groovy-all:${versions.groovy}"
compile "org.gradle:gradle-base-services:${versions.gradle}"
compile "org.gradle:gradle-base-services-groovy:${versions.gradle}"
compile "org.gradle:gradle-core:${versions.gradle}"
compile files("lib/gradle-platform-jvm-${versions.gradle}.jar")
}
注意:
gradle的核心依赖项应该通过公共工件ID引用(而不是通过直接JAR文件引用)。这种方式在运行时gradle使用关联的POM来构建传递的运行时依赖项。否则,在执行单元测试期间,您将获得NoClassDefFoundError,因为其他gradle的内部不在执行类路径中。
看起来并非所有gradle的工件都可以在公共存储库(jcenter)中使用。如果你的插件中你要构建对其他“本机”任务的依赖(比如'jar') - 它们的实现必须直接通过JAR文件引用。