【发布时间】:2021-08-07 10:05:54
【问题描述】:
在 Mockk 中访问私有变量时,无法设置私有属性的值。
我们有 CustomerImpl 类,它有 1 个名为 customerData 的私有属性。
我们希望在不调用 updateCache() 方法的情况下从我们的测试用例中设置私有属性 customerData 中的数据。
我们正在使用 Mockk 1.10.6
CustomerImpl 类
class CustomerImpl {
private var customerData : MutableList<CustomerModel> = mutableListOf()
private fun updateCache() {
... here customerData is updated.
}
fun clearCache() {
if(customerData.isNotEmpty())
customerData.clear()
}
}
测试类
class CustomerImplTest {
private lateinit var customerImpl: CustomerImpl
@Before
fun setUp() {
MockKAnnotations.init(this)
customerImpl = spyk(CustomerImpl(), recordPrivateCalls = true)
}
@Test
fun clearCacheTest() {
val customer = listOf(CustomerModel(id = "3", name = "John"))
every { customerImpl setProperty "customer" value customer } just Runs
customerImpl.clearCache()
}
}
当我们尝试运行这个测试用例时,它给了我们以下错误。
例外
io.mockk.MockKException: Missing mocked calls inside every { ... } block: make sure the object inside the block is a mock
at io.mockk.impl.recording.states.StubbingState.checkMissingCalls(StubbingState.kt:14)
at io.mockk.impl.recording.states.StubbingState.recordingDone(StubbingState.kt:8)
at io.mockk.impl.recording.CommonCallRecorder.done(CommonCallRecorder.kt:47)
at io.mockk.impl.eval.RecordedBlockEvaluator.record(RecordedBlockEvaluator.kt:60)
at io.mockk.impl.eval.EveryBlockEvaluator.every(EveryBlockEvaluator.kt:30)
at io.mockk.MockKDsl.internalEvery(API.kt:92)
at io.mockk.MockKKt.every(MockK.kt:98)
at com.xyz.impl.CustomerImplTest.clearCacheTest(CustomerImplTest.kt:60)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.junit.rules.ExternalResource$1.evaluate(ExternalResource.java:48)
at org.junit.rules.RunRules.evaluate(RunRules.java:20)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:230)
at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:58)
我们只在 Mockk 中寻找解决方案。
【问题讨论】:
-
所以根据我对问题的理解,您想在测试开始时将属性
customerData设置为指定值吗?我认为您当前实际上所做的是告诉 mockk,当您运行测试并且属性设置为该数据时,继续。 -
据我所知,用 mockk 模拟私有变量是不可能的——不过你可以模拟私有方法。也许考虑使用
@VisibleForTesting注释 -
stackoverflow.com/questions/51316105/mock-a-private-property 我个人认为如果你需要调用更新方法或通过构造函数注入 mutableList 是可以的
标签: android kotlin junit4 mockk