使用 MockK 和 Kotlin 在 @SpringBootTest 中出现 UninitializedPropertyAccessException 的原因是什么?

What is the reason for an UninitializedPropertyAccessException in @SpringBootTest with MockK and Kotlin?

我正在尝试将 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.invoke(RetransformInlineInstrumnetation.kt:19)
at io.mockk.proxy.common.transformation.RetransformInlineInstrumnetation$execute.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 也会发生同样的情况。导入的服务与测试是在相同的还是不同的包中都没有关系class。)

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

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)
    }
}

A​​utowiring 不工作...所以我的错是什么?我怎样才能完成测试 运行?

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

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

我在另一个线程上创建了一个关于如何设置单元测试的 post,与您的要求相当: