首页 > 解决方案 > 使用 MockK 和 Kotlin 在 @SpringBootTest 中出现 UninitializedPropertyAccessException 的原因是什么?

问题描述

我正在尝试将 MockK 1.10.2 与 Kotlin 1.4.10 和 @SpringBootTest (Spring Boot 2.2.2.RELEASE) 一起使用,但由于

OpenJDK 64-Bit Server VM warning: Sharing is only supported for boot     loader classes because bootstrap classpath has been appended
2020-11-05 15:00:37.878  WARN   --- [           main] i.m.p.j.t.InliningClassTransformer       : Failed to transform class java/lang/Object

java.lang.IllegalArgumentException: Unsupported class file major version 59
at net.bytebuddy.jar.asm.ClassReader.<init>(ClassReader.java:195)
at net.bytebuddy.jar.asm.ClassReader.<init>(ClassReader.java:176)
at net.bytebuddy.jar.asm.ClassReader.<init>(ClassReader.java:162)
at net.bytebuddy.utility.OpenedClassReader.of(OpenedClassReader.java:86)
at net.bytebuddy.dynamic.scaffold.TypeWriter$Default$ForInlining.create(TypeWriter.java:3394)
at net.bytebuddy.dynamic.scaffold.TypeWriter$Default.make(TypeWriter.java:1933)
at net.bytebuddy.dynamic.scaffold.inline.RedefinitionDynamicTypeBuilder.make(RedefinitionDynamicTypeBuilder.java:217)
at net.bytebuddy.dynamic.scaffold.inline.AbstractInliningDynamicTypeBuilder.make(AbstractInliningDynamicTypeBuilder.java:120)
at net.bytebuddy.dynamic.DynamicType$Builder$AbstractBase.make(DynamicType.java:3404)
at io.mockk.proxy.jvm.transformation.InliningClassTransformer.transform(InliningClassTransformer.kt:77)
at java.instrument/java.lang.instrument.ClassFileTransformer.transform(ClassFileTransformer.java:246)
at java.instrument/sun.instrument.TransformerManager.transform(TransformerManager.java:188)
at java.instrument/sun.instrument.InstrumentationImpl.transform(InstrumentationImpl.java:563)
at java.instrument/sun.instrument.InstrumentationImpl.retransformClasses0(Native Method)
at java.instrument/sun.instrument.InstrumentationImpl.retransformClasses(InstrumentationImpl.java:167)
at io.mockk.proxy.jvm.transformation.JvmInlineInstrumentation.retransform(JvmInlineInstrumentation.kt:28)
at io.mockk.proxy.common.transformation.RetransformInlineInstrumnetation$execute$1.invoke(RetransformInlineInstrumnetation.kt:19)
at io.mockk.proxy.common.transformation.RetransformInlineInstrumnetation$execute$1.invoke(RetransformInlineInstrumnetation.kt:6)
at io.mockk.proxy.common.transformation.ClassTransformationSpecMap.applyTransformation(ClassTransformationSpecMap.kt:41)
at io.mockk.proxy.common.transformation.RetransformInlineInstrumnetation.execute(RetransformInlineInstrumnetation.kt:16)
at io.mockk.proxy.jvm.ProxyMaker.inline(ProxyMaker.kt:88)
at io.mockk.proxy.jvm.ProxyMaker.proxy(ProxyMaker.kt:30)

kotlin.UninitializedPropertyAccessException: lateinit property taService has not been initialized

例外。(如果我使用 tmpService 也会发生同样的情况。导入的服务与测试类位于相同还是不同的包中都没有关系。)

正如您从我的测试类的代码中看到的那样,我已经玩了很多,但到目前为止没有任何成功。

package com.xxx.emr.tm

import com.xxx.data.emr.model.PatientAssignment
import com.xxx.data.tm.TMPService
import com.xxx.data.tm.model.MyType
import com.xxx.data.tm.model.MyTypeCode
import com.xxx.data.tm.model.UserAction
import com.xxx.emr.service.model.AuthenticatedUser
import io.mockk.every
import io.mockk.impl.annotations.InjectMockKs
import io.mockk.impl.annotations.SpyK
import io.mockk.junit5.MockKExtension
import io.mockk.mockk
import io.mockk.mockkObject
import io.mockk.verify
import org.junit.Test
import org.junit.jupiter.api.extension.ExtendWith
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.context.SpringBootTest

 @ExtendWith(SpringExtension::class, MockKExtension::class)
 @SpringBootTest // (classes = [com.xxx.emr.service.MyServiceSpringBoot::class])
// @RunWith(SpringJUnit4ClassRunner::class)    
// @ActiveProfiles("test")
// @EnableAutoConfiguration
// @AutoConfigureMockMvc
class MyTest {
// (
//    val tmpService: TMPService,
//    val taService: TaService
// )

//    @InjectMockKs
//    @Autowired
//    @SpyK
@MockK
private lateinit var tmpService: TMPService

@InjectMockKs
@Autowired
private lateinit var taService: TaService

@Test
fun assignAToB() {
    
    MockKAnnotations.init(this, relaxUnitFun = true)

    val vId = "xxx"
    val authUser: AuthenticatedUser = AuthenticatedUser.mockedUser()
    val userAction = UserAction(
        userId = "user_id",
        actionCode = ActionType.GET_IT,
        sessionId = "sessionId"
    )

    val xxx = MyType(
        MyTypeCode.ABC.value,
        MyTypeCode.ABC.name,
    )

    val actionResult = UserActionResult(hashMapOf("success" to true))

//        every { tmpService.getXxx(any()) } returns xxx

    verify( exactly = 1 ) {
        tmpService.doSomething(any(), any(), any())
    }

    verify( exactly = 1 ) {
         taService.dowhatYouWant(„vId", authUser, userAction)
    }
}

自动装配不起作用......那我的错是什么?我怎样才能让测试运行呢?

标签: kotlinspring-boot-testmockk

解决方案


我认为你应该首先初始化你的模拟,例如在你的测试文件中添加这个:

@org.springframework.test.context.event.annotation.BeforeTestMethod
fun initMocks() {
    org.mockito.MockitoAnnotations.initMocks(this)
}

我在另一个线程上创建了一篇关于如何设置单元测试的帖子,与您的要求相当: https ://stackoverflow.com/a/64669499/7919904


推荐阅读