Grails 4.0.11升级后运行Spock单元测试报AbstractMethodError异常
Grails 4升级后Spock单元测试抛出AbstractMethodError解决方案
问题背景
- 应用从Grails 3版本升级至Grails 4.0.11,由于Grails 3使用的Mixin机制自3.3版本起被移除,升级后改用Spock框架编写单元测试用例。
复现代码
编写示例Domain类Person与对应测试类PersonSpec,测试类继承Specification并实现DomainUnitTest<Person>接口,代码如下:
class Person { String firstName String lastName static constraints = { } } class PersonSpec extends Specification implements DomainUnitTest<Person> { def setup() { } def cleanup() { } void "test something"() { expect:"fix me" true == false } }
异常信息
运行上述测试用例时抛出java.lang.AbstractMethodError,提示类org.grails.testing.gorm.spock.DataTestSetupSpecInterceptor未实现groovy.lang.GroovyObject接口的abstract java.lang.Object getProperty(java.lang.String)方法,完整错误栈:
java.lang.AbstractMethodError: Receiver class org.grails.testing.gorm.spock.DataTestSetupSpecInterceptor does not define or inherit an implementation of the resolved method 'abstract java.lang.Object getProperty(java.lang.String)' of interface groovy.lang.GroovyObject. at groovy.lang.Closure.getPropertyTryThese(Closure.java:313) at groovy.lang.Closure.getPropertyOwnerFirst(Closure.java:307) at groovy.lang.Closure.getProperty(Closure.java:296) at org.grails.testing.gorm.spock.DataTestSetupSpecInterceptor.setupDataTestBeans_closure1(DataTestSetupSpecInterceptor.groovy:39) at org.grails.testing.gorm.spock.DataTestSetupSpecInterceptor.setupDataTestBeans_closure1(DataTestSetupSpecInterceptor.groovy) at groovy.lang.Closure.call(Closure.java:405) at groovy.lang.Closure.call(Closure.java:399) at grails.spring.BeanBuilder.invokeBeanDefiningClosure(BeanBuilder.java:759) at grails.spring.BeanBuilder.beans(BeanBuilder.java:588) at org.grails.testing.GrailsUnitTest$Trait$Helper.defineBeans(GrailsUnitTest.groovy:97) at org.grails.testing.gorm.spock.DataTestSetupSpecInterceptor.setupDataTestBeans(DataTestSetupSpecInterceptor.groovy:38) at org.grails.testing.gorm.spock.DataTestSetupSpecInterceptor.configureDataTest(DataTestSetupSpecInterceptor.groovy:66) at org.grails.testing.gorm.spock.DataTestSetupSpecInterceptor.intercept(DataTestSetupSpecInterceptor.groovy:31) at org.spockframework.runtime.extension.MethodInvocation.proceed(MethodInvocation.java:97) at org.junit.runner.JUnitCore.run(JUnitCore.java:137) at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:69) at com.intellij.rt.junit.IdeaTestRunner$Repeater$1.execute(IdeaTestRunner.java:38) at com.intellij.rt.execution.junit.TestsRepeater.repeat(TestsRepeater.java:11) at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:35) at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:235) at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:54)
问题根因
该异常属于典型的二进制依赖版本不兼容问题:
- 抛出错误的
DataTestSetupSpecInterceptor属于Grails测试支持包,该类编译时依赖的Groovy版本与测试运行时实际加载的Groovy版本不一致,导致GroovyObject接口要求实现的getProperty(String)方法签名不匹配,运行时找不到对应实现。 - 该问题在Grails 3升4的场景中非常常见,通常是升级时未同步对齐测试依赖版本,或手动指定了不兼容的Groovy、Spock版本,覆盖了Grails官方BOM管理的兼容版本导致的。
修复步骤
- 对齐依赖版本:打开项目
build.gradle配置文件,删除所有手动指定的Groovy、Spock、grails-gorm-testing-support、grails-testing-support依赖的版本号,统一使用Grails 4.0.11官方BOM导入的兼容版本。Grails 4.0.x线的官方兼容依赖版本为:Groovy 2.5.x、Spock 1.3-groovy-2.5、grails-testing-support 4.0.1。 - 排查依赖冲突:执行
./gradlew dependencies --configuration testRuntimeClasspath命令输出测试运行时类路径的依赖树,排查是否有其他依赖传递引入了跨大版本的Groovy或Grails测试包,手动排除冲突版本,确保所有Groovy相关依赖版本统一为2.5.x系列。 - 清理缓存重测:执行
./gradlew clean test命令清理旧构建产物与缓存后重新运行测试,避免旧版本编译的类文件残留触发异常。
注意:Grails 4.x系列最高仅兼容Groovy 2.5.x、Spock 1.3.x版本,手动升级到Groovy 3+、Spock 2+会持续触发二进制兼容错误,无特殊需求不要跨大版本升级这两个依赖。
内容的提问来源于stack exchange,提问作者Zaid Khan
相关产品推荐
相关产品推荐

