【发布时间】:2016-01-19 13:21:51
【问题描述】:
我正在尝试将一个 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 中编译它,我必须在 build.gradle 中指定以下内容:
dependencies {
compile gradleApi()
}
这渗透到我的项目中捕获所有 gradle 依赖项。虽然我仍然看不到修复它的方法:
- 我无法删除它,因为项目无法编译
- 我不能排除某些东西,因为 gradle 不支持
gradleApi()(参见 http://gradle.1045684.n5.nabble.com/exclude-some-dependencies-from-gradleApi-dependency-td5712103.html)。 - 我不能只添加那些我真正需要的 gradle jar 作为依赖项——我没有看到任何在编译依赖项中明确引用它们的方法,我没有看到任何包含这些工件的公共存储库。注意:对于 MAVEN 构建,我已手动将它们上传到本地 MAVEN 存储库。
【问题讨论】:
-
是您尝试使用 FileUtils.write 但旧版本 (1.4) 没有该方法(类“碰撞”)的问题吗?
-
这是正在发生的问题,但根本问题略有不同 - 我在插件中引用的库使用较新版本的 commons-io,而 gradle 提供的运行时提供较旧的一。所以...... gradle 应该以某种方式在测试时提供 ClassLoaders 的分离,以让“自己的代码”和“单元测试中的插件代码”与不同版本的 3rd 方库共存。
-
Gradle 在这里做的是正确的事情,并保护您免受不正确的测试。当你的插件被加载时,它会运行到你的测试看到的同一个 jar 不匹配中。我会尝试使用 Java8 或 Groovy 来解决需要这个库的问题。
-
我不同意“Gradle 在这里做正确的事情”。在“测试时间”和“运行时间”,目标插件中类的内部引用(在这种情况下是 commons-io)应该与 gradle 的内部引用隔离。 MAVEN 通过专用的 ClassLoaders 执行插件代码的“测试”和“运行时”。
-
但是当插件执行时,它将首先在类路径上加载所有内部 jar。所以它的行为就像你的插件一样。
标签: gradle