gpt4 book ai didi

android - PowerMockito spy : Calling real method results with CannotStubVoidMethodWithReturnValue

转载 作者:行者123 更新时间:2023-11-29 23:57:09 26 4
gpt4 key购买 nike

我开始撞墙了,但我完全不明白如何在 spy 类上调用真正的方法。

长话短说,我正在监视我的测试类以 stub 一个私有(private)方法。然后我想调用测试类的真实 void 方法,但它说

'testedMethod' is a void method and it cannot be stubbed with a return value!

问题是我不需要它被 stub 。我也试过 doCallRealMethod(),没用。

我正在使用 Kotlin 和 Android Studio 为我的 Android 项目运行一些单元测试。我有以下要测试的类(class):

class MyClass {
fun persistDeviceData(deviceInfo: DeviceInfo, saveCallback: SaveCallback) {
val deviceObject = getDeviceObject()
// some setters from deviceInfo here
deviceObject.saveInBackground(callback)
}

// This method is created for unit testing purposes
private fun getDeviceObject(): MyDeviceObject{
return MyDeviceObject("someStringArgument")
}
}

这里是测试类

import io.kotlintest.KTestJUnitRunner
import io.kotlintest.specs.BehaviorSpec
import junit.framework.Assert
import org.junit.runner.RunWith
import org.mockito.Mockito

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())
// Mocking private method call
PowerMockito.doReturn(deviceObject).`when`(testedRepo,
PowerMockito.method(
MyClass::class.java,
"getDeviceObject"))
val a = SaveCallback { // Callback handling here }
// Calling REAL method of spy class. Here it fails
myClassTest.persistDeviceData(DeviceInfo(), a)
Assert.assertTrue(true)
}

}

在下一行调用实际方法时测试失败

myClassTest.persistDeviceData(DeviceInfo(), a)

这是错误堆栈跟踪

org.mockito.exceptions.misusing.CannotStubVoidMethodWithReturnValue: 'persistDeviceData' is a void method and it cannot be stubbed with a return value! Voids are usually stubbed with Throwables: doThrow(exception).when(mock).someVoidMethod(); If you need to set the void method to do nothing you can use: doNothing().when(mock).someVoidMethod(); For more information, check out the javadocs for Mockito.doNothing().


If you're unsure why you're getting above error read on. Due to the nature of the syntax above problem might occur because: 1. The method you are trying to stub is overloaded. Make sure you are calling the right overloaded version. 2. Somewhere in your test you are stubbing final methods. Sorry, Mockito does not verify/stub final methods. 3. A spy is stubbed using when(spy.foo()).then() syntax. It is safer to stub spies - - with doReturn|Throw() family of methods. More in javadocs for Mockito.spy() method. 4. Mocking methods declared on non-public parent classes is not supported.

at MyClassTest.<init>(MyClass.kt:46)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at java.lang.Class.newInstance(Class.java:442)
at io.kotlintest.KTestJUnitRunner.<init>(KTestJUnitRunner.kt:9)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at org.powermock.reflect.internal.WhiteboxImpl.createInstance(WhiteboxImpl.java:1414)
at org.powermock.reflect.internal.WhiteboxImpl.invokeConstructor(WhiteboxImpl.java:1262)
at org.powermock.reflect.Whitebox.invokeConstructor(Whitebox.java:497)
at org.powermock.modules.junit4.internal.impl.DelegatingPowerMockRunner$1.call(DelegatingPowerMockRunner.java:101)
at org.powermock.modules.junit4.internal.impl.DelegatingPowerMockRunner$1.call(DelegatingPowerMockRunner.java:97)
at org.powermock.modules.junit4.internal.impl.DelegatingPowerMockRunner.withContextClassLoader(DelegatingPowerMockRunner.java:132)
at org.powermock.modules.junit4.internal.impl.DelegatingPowerMockRunner.createDelegate(DelegatingPowerMockRunner.java:96)
at org.powermock.modules.junit4.internal.impl.DelegatingPowerMockRunner.<init>(DelegatingPowerMockRunner.java:64)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at org.powermock.modules.junit4.common.internal.impl.JUnit4TestSuiteChunkerImpl.createDelegatorFromClassloader(JUnit4TestSuiteChunkerImpl.java:165)
at org.powermock.modules.junit4.common.internal.impl.JUnit4TestSuiteChunkerImpl.createDelegatorFromClassloader(JUnit4TestSuiteChunkerImpl.java:47)
at org.powermock.tests.utils.impl.AbstractTestSuiteChunkerImpl.createTestDelegators(AbstractTestSuiteChunkerImpl.java:107)
at org.powermock.modules.junit4.common.internal.impl.JUnit4TestSuiteChunkerImpl.<init>(JUnit4TestSuiteChunkerImpl.java:69)
at org.powermock.modules.junit4.common.internal.impl.AbstractCommonPowerMockRunner.<init>(AbstractCommonPowerMockRunner.java:36)
at org.powermock.modules.junit4.PowerMockRunner.<init>(PowerMockRunner.java:34)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at org.junit.internal.builders.AnnotatedBuilder.buildRunner(AnnotatedBuilder.java:104)
at org.junit.internal.builders.AnnotatedBuilder.runnerForClass(AnnotatedBuilder.java:86)
at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:59)
at org.junit.internal.builders.AllDefaultPossibilitiesBuilder.runnerForClass(AllDefaultPossibilitiesBuilder.java:26)
at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:59)
at org.junit.internal.requests.ClassRequest.getRunner(ClassRequest.java:33)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:49)
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)

最佳答案

回答我自己的问题 - 我错误地使用了 PowerMockito 的 .when() 方法。这是有效的代码:

@RunWith(PowerMockRunner::class)
@PrepareForTest(MyClass::class, DeviceObject::class)
class DeviceRepositoryImplTest{

private val testedRepo = PowerMockito.spy(MyClass())
private val deviceObject = PowerMockito.mock(DeviceObject())

@Test
fun persistDeviceData_ok(){
// Mocking private method
PowerMockito.`when`<ParseObject>(testedRepo,
PowerMockito.method(
MyClass::class.java,
"getDeviceObject")).withNoArguments().thenReturn(deviceObject)

// Creating callback for tested method
val callback = SaveCallback {
...
}

...

testedRepo.persistDeviceData(DeviceInfo(), callback)

}

关于android - PowerMockito spy : Calling real method results with CannotStubVoidMethodWithReturnValue,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50244955/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com