测试中的类如下所示:
class State(pivate val repo){
val values = listOf<Int>()
fun update() {
values = repo.generateValues() // <-line 375
}
}单元测试看起来像:
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
private class StateTest {
@MockK(relaxed = true) private lateinit var mockedRepo: Repo
@BeforeAll
fun config() {
MockKAnnotations.init(this)
}
@BeforeEach
fun setup() {
clearAllMocks()
unmockkAll()
}
@Test
fun `invoke update`() {
val state = mockk<State>(relaxed = true)
every { state.repo } answers { mockedRepo }
every { mockedRepo.generateValues() } returns listOf(1,2,3)
every { state.update() } answers { callOriginal() }
state.update()
Assertions.assertTrue(state.values.size > 0)
}
}运行测试,将抛出一个NullPointerException:
java.lang.NullPointerException
at com.name.someapp.someservice.State.update(State.kt:375)
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 io.mockk.proxy.jvm.advice.MethodCall.call(MethodCall.kt:14)
at io.mockk.proxy.jvm.advice.SelfCallEliminatorCallable.call(SelfCallEliminatorCallable.kt:14)
at io.mockk.impl.instantiation.JvmMockFactoryHelper.handleOriginalCall(JvmMockFactoryHelper.kt:95)
at io.mockk.impl.instantiation.JvmMockFactoryHelper.access$handleOriginalCall(JvmMockFactoryHelper.kt:18)
at io.mockk.impl.instantiation.JvmMockFactoryHelper$mockHandler$1$invocation$$inlined$stdFunctions$lambda$1.invoke(JvmMockFactoryHelper.kt:27)
at io.mockk.impl.stub.MockKStub$handleInvocation$originalPlusToString$1.invoke(MockKStub.kt:230)
at io.mockk.MockKAnswerScope.callOriginal(API.kt:2205)发布于 2022-08-11 09:31:40
获得NullPointerException的原因是,fun update()不调用getRepo() (您已经对其进行了嘲弄),而是直接使用支持字段repo。(您可以通过将Kotlin源代码编译为字节码并在IntelliJ的思想中将其反编译为Java来看到这一点。)这在kotlinlang.org上也有记录。
JVM上的I:对带有默认getter和setter的私有属性的访问进行了优化,以避免函数调用开销。
正如sidgate在评论中所说,答案是创建一个真实的(而不是模拟的) State实例,并将模拟回购传递给它的构造函数:
val state = State(mockRepo)这是一种模仿“被测试系统”的代码气味。
https://stackoverflow.com/questions/73315397
复制相似问题