You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spock中Mock的属性值无法被Kotlin代码读取该如何解决?

问题诱因
  • GroovyMock的拦截逻辑仅对Groovy动态调用生效:GroovyMock基于Groovy动态元编程实现,仅能拦截Groovy代码侧的方法调用。Kotlin代码是静态编译的,调用类方法时走JVM静态分派逻辑,不会触发Groovy的动态拦截,会直接读取类实例的字段值,你没有给Mock实例的prop字段赋值,所以读取结果为null。
  • Kotlin类成员默认是final修饰:你的TestEntity虽然标记了open,但内部的prop属性没有额外加open修饰,其对应的getProp()、setProp()方法默认是final的,常规Spock Mock(基于ByteBuddy实现)无法Stub final方法,这也是你替换为普通Mock后Groovy侧也读不到值的原因。
解决方案

方案1:直接使用真实实体实例(最推荐)

对于无复杂逻辑的简单实体类,不需要Mock,直接构造真实实例传入即可,无任何兼容问题:

given:
def cut = new AClassUnderTest()
def testEntity = new TestEntity("abc")

方案2:修改Kotlin代码允许方法重写,使用普通Spock Mock

给prop属性添加open修饰,允许getter方法被重写:

open class TestEntity(open var prop: String) {
}

测试代码使用普通Mock而非GroovyMock:

def testEntityMock = Mock(TestEntity)
testEntityMock.getProp() >> "abc"
// 也可以直接写 testEntityMock.prop >> "abc" 效果一致

方案3:无需修改生产代码,直接给Mock实例的字段赋值

Groovy支持直接访问类的私有字段,你可以直接给prop字段赋值,这样不管是Kotlin还是Groovy侧读取都能拿到值:

given:
def testEntityMock = GroovyMock(TestEntity)
testEntityMock.@prop = "abc" // 直接给实例的prop字段赋值,不走getter/setter

方案4:开启Spock Final方法Mock能力

如果你使用Spock 2.0+版本,可以开启Final类/方法Mock能力,不需要修改生产代码的open修饰:

  1. 在测试资源路径下新建META-INF/services/org.spockframework.mock.IMockFactory文件,写入以下内容:
org.spockframework.mock.bytebuddy.ByteBuddyMockFactory
  1. 测试代码使用普通Mock即可Stub final方法:
def testEntityMock = Mock(TestEntity)
testEntityMock.prop >> "abc"

内容的提问来源于stack exchange,提问作者Brendan Hill

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.21 18:45:04