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
相关产品推荐
相关产品推荐

