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

PowerMockito Spy调用真实方法报错:CannotStubVoidMethodWithReturnValue

解决PowerMockito Spy测试void方法时的"CannotStubVoidMethodWithReturnValue"错误

这个问题的核心是mock私有方法时的语法错误,导致PowerMockito误将你调用真实void方法的操作当成了试图给它存根返回值的操作。咱们一步步来修复:

问题根源

看你的测试代码,mock私有方法那一行存在两个关键问题:

PowerMockito.doReturn(deviceObject).`when`(testedRepo, PowerMockito.method(MyClass::class.java, "getDeviceObject"))
  • 对象引用错误:你spy的实例是myClassTest,但这里写了testedRepo,PowerMockito找不到正确的目标对象,进而引发语法误解。
  • 语法冗余且易出错:使用PowerMockito.method()的写法没必要,直接指定方法名的重载写法更简洁可靠。

修复步骤

1. 修正私有方法的mock语法

把mock私有方法的代码改成下面这样,确保目标是你创建的spy实例myClassTest:

// 正确mock私有方法:指定spy实例+方法名
PowerMockito.doReturn(deviceObject).`when`(myClassTest, "getDeviceObject")

你也可以用另一种等价的简洁写法:

PowerMockito.when(myClassTest, "getDeviceObject").thenReturn(deviceObject)

这两种写法都能让私有方法getDeviceObject返回你预先创建的mock对象deviceObject。

2. 直接调用真实方法即可

spy对象默认会调用真实方法,你调用myClassTest.persistDeviceData(DeviceInfo(), a)时不需要额外添加doCallRealMethod()存根,直接调用就行。

完整修正后的测试代码

import io.kotlintest.KTestJUnitRunner
import io.kotlintest.specs.BehaviorSpec
import org.junit.Assert.assertTrue
import org.junit.runner.RunWith
import org.powermock.api.mockito.PowerMockito
import org.powermock.core.classloader.annotations.PrepareForTest
import org.powermock.modules.junit4.PowerMockRunner
import org.powermock.modules.junit4.PowerMockRunnerDelegate

@RunWith(PowerMockRunner::class)
@PowerMockRunnerDelegate(KTestJUnitRunner::class)
@PrepareForTest(MyClass::class)
class MyClassTest: BehaviorSpec(){
    init {
        val deviceObject = PowerMockito.mock(MyDeviceObject::class.java)
        val myClassTest = PowerMockito.spy(MyClass())

        // 修正后的私有方法mock逻辑
        PowerMockito.doReturn(deviceObject).`when`(myClassTest, "getDeviceObject")

        val a = SaveCallback { 
            // Callback handling here 
        }

        // 直接调用spy的真实void方法
        myClassTest.persistDeviceData(DeviceInfo(), a)
        assertTrue(true)
    }
}

额外注意事项

  • 确保@PrepareForTest(MyClass::class)注解正确添加,PowerMockito需要修改该类的字节码才能mock私有方法。
  • 如果MyDeviceObject是final类,需要把它也加入@PrepareForTest参数中,比如@PrepareForTest(MyClass::class, MyDeviceObject::class),否则PowerMockito无法mock这个类。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 04:28:20