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

Mockito模拟带val构造参数的Kotlin类属性问题

解决Kotlin DeviceProxy类的Mock问题

方案一:Spy包装真实实例

Kotlin中val属性的getter是final方法,默认Mockito无法mock final成员。你可以先创建真实的DeviceProxy实例(搭配mock的Context),再用Spy包装,既能复用构造逻辑,也能按需控制属性行为:

// Mock Context依赖
val mockContext = mock(Context::class.java)
// 创建真实实例,传入测试用name
val realDevice = DeviceProxy(mockContext, TEST_DEVICE_NAME)
// 转为Spy以便修改行为(若不需要动态修改,直接用realDevice即可)
val deviceMock = spy(realDevice)

// 如需动态修改name返回值(可选)
doReturn(TEST_DEVICE_NAME).whenever(deviceMock).name

前置配置:需要开启Mockito对final类/方法的支持,在src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker文件中添加:

mock-maker-inline

方案二:用mockConstructor拦截构造(无需真实实例)

确保Mockito版本≥3.5.0,且已配置上述inline mock maker。正确的mockConstructor用法如下:

// 拦截DeviceProxy的构造函数
try (MockedConstruction<DeviceProxy> mocked = mockConstructor(DeviceProxy::class.java) { mock ->
    // 定义mock实例的属性行为
    whenever(mock.name).thenReturn(TEST_DEVICE_NAME)
}) {
    // 此代码块内构造的DeviceProxy都会是我们定义的mock
    val deviceMock = DeviceProxy(mock(Context::class.java), "任意占位符")
    // 此时deviceMock.name返回TEST_DEVICE_NAME
    assert(deviceMock.name == TEST_DEVICE_NAME)
}

原代码出错原因

直接mockDeviceProxy后尝试mockname属性失败,是因为name的getter是final方法,默认Mockito不支持mock final成员,必须开启inline mock maker才能拦截这类调用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 23:20:43