Gradle小版本升级致测试编译失败,求确认Groovy实际版本
核心问题:实际使用的Groovy版本
你当前编译测试代码时实际使用的是Gradle 2.4自带的Groovy 2.3.10,而非你在依赖中声明的groovy-all:2.4.11。
Gradle的Groovy编译任务(比如compileTestGroovy)默认会使用Gradle自身捆绑的Groovy版本来编译Groovy代码,而不是直接使用项目依赖里的Groovy。虽然你的项目依赖了Groovy 2.4.11,但编译阶段Gradle优先用内置的2.3.10,这就造成了Groovy版本的不一致,进而触发了泛型相关的编译问题。
为什么会出现类型转换错误?
Groovy 2.3.x和2.4.x在泛型擦除与内部类继承泛型父类的处理逻辑上存在差异。当Gradle用2.3.10编译你的Spock测试时,生成的Java存根文件错误地将TestDetailsSortKey继承的泛型类型TestDetails擦除成了父类Details,导致在调用父类构造方法时出现Details无法转换为TestDetails的类型不兼容错误。
你提到的Groovy泛型Bug虽然在2.3.8修复,但这个场景下的内部类泛型处理问题可能是2.3.10仍存在的边缘情况,而2.4.x版本已经修复了这个问题——但因为Gradle没用到你依赖的2.4.11,所以问题依然存在。
解决方案
1. 强制Gradle使用项目依赖的Groovy版本编译
在你的build.gradle中添加配置,让Groovy编译任务使用项目依赖的Groovy类路径,而不是Gradle内置的:
compileTestGroovy { groovyClasspath = configurations.testCompile }
这样compileTestGroovy就会使用你声明的groovy-all:2.4.11来编译测试代码,泛型处理逻辑会更正确,应该能解决类型转换错误。
2. 对齐Gradle内置Groovy版本(不推荐)
如果你暂时不想调整编译配置,可以将项目依赖的Groovy版本改为和Gradle 2.4内置的2.3.10一致:
compile "org.codehaus.groovy:groovy-all:2.3.10"
但这可能会影响项目中其他依赖Groovy 2.4.x特性的代码,所以仅作为临时 workaround。
3. 升级Gradle版本(推荐长期方案)
Gradle 2.x版本比较老旧,后续的Gradle 3.x及以上版本捆绑了更高版本的Groovy(比如Gradle 3.0用Groovy 2.4.4),不仅修复了更多泛型相关的Bug,也对Spock的兼容性更好。升级Gradle到较新的稳定版本,能从根源上避免这类版本冲突问题。
验证Groovy版本的方法
你可以通过以下命令确认Gradle内置的Groovy版本:
./gradlew properties | grep groovyVersion
另外,查看测试编译类路径的完整依赖树,确认实际生效的Groovy版本:
./gradlew dependencies --configuration testCompileClasspath
内容的提问来源于stack exchange,提问作者Jazzschmidt

