【问题标题】:MockK causing a StackOverflowExceptionMockK 导致 StackOverflowException
【发布时间】:2021-02-09 21:11:02
【问题描述】:

作为标题!我无法运行任何使用 MockK 的测试,因为它们最终会在初始化期间抛出 StackOverflowError。

例如,这是我的一个测试类:

@ExtendWith(MockKExtension::class)
class DBSequencesServicesTest {
    private lateinit var service: DBSequencesService

    @MockK
    private lateinit var sequencesRepo: DBSequencesRepo

    @BeforeTest
    fun initService() {
        service = DBSequencesServiceImpl(sequencesRepo)
    }

    @Test
    fun `should return value 0 if given a non-existent sequence`() {
        every { sequencesRepo.findById(any()) } returns Optional.empty()
        assertEquals(0, service.nextValue("test"))
    }

    @Test
    fun `should return next value if given an existing sequence`() {
        every { sequencesRepo.findById("test") } returns Optional.of(DBSequence("test", 1))
        every { sequencesRepo.save(any()) } returnsArgument 0
        assertEquals(1, service.nextValue("test"))
    }

    @Test
    fun `successive calls should return incrementing values`() {
        every { sequencesRepo.findById("test") } returnsMany listOf(
            Optional.of(DBSequence("test", 0)),
            Optional.of(DBSequence("test", 1)),
            Optional.of(DBSequence("test", 2))
        )
        every { sequencesRepo.save(any()) } returnsArgument 0

        for (i in 0L..2L) {
            assertEquals(i, service.nextValue("test"))
        }
    }
}

这是产生的堆栈跟踪,一旦模式变得明显就会被切断:

Exception in thread "Test worker" java/lang/StackOverflowError
    at io/mockk/proxy/jvm/dispatcher/JvmMockKDispatcher.get (JvmMockKDispatcher.java:16)
    at java/lang/Object.hashCode (Object.java:119)
    at java/util/HashMap.hash (HashMap.java:339)
    at java/util/HashMap.get (HashMap.java:557)
    at sun/reflect/Reflection.filterMethods (Reflection.java:291)
    at java/lang/Class.getMethodHelper (Class.java:1265)
    at java/lang/Class.getMethod (Class.java:1191)
    at java/lang/Object.hashCode (Object.java:119)
    at java/util/HashMap.hash (HashMap.java:339)
    at java/util/HashMap.get (HashMap.java:557)
    at sun/reflect/Reflection.filterMethods (Reflection.java:291)
    at java/lang/Class.getMethodHelper (Class.java:1265)
    at java/lang/Class.getMethod (Class.java:1191)
    at java/lang/Object.hashCode (Object.java:119)
    at java/util/HashMap.hash (HashMap.java:339)
    at java/util/HashMap.get (HashMap.java:557)
    at sun/reflect/Reflection.filterMethods (Reflection.java:291)
    at java/lang/Class.getMethodHelper (Class.java:1265)
    at java/lang/Class.getMethod (Class.java:1191)
    at java/lang/Object.hashCode (Object.java:119)
    at java/util/HashMap.hash (HashMap.java:339)
    at java/util/HashMap.get (HashMap.java:557)
    ...

然后抛出 MessageIOException:

org.gradle.internal.remote.internal.MessageIOException: Could not read message from '/127.0.0.1:52775'.
    at org.gradle.internal.remote.internal.inet.SocketConnection.receive(SocketConnection.java:94)
    at org.gradle.internal.remote.internal.hub.MessageHub$ConnectionReceive.run(MessageHub.java:270)
    at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:64)
    at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:48)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:56)
    at java.lang.Thread.run(Thread.java:821)

据我所知,我已经正确设置了 MockK,并且正在根据他们的指南使用它:

dependencies {
    // Other dependencies go here...
    testImplementation("org.springframework.boot:spring-boot-starter-test") {
        exclude(group = "org.junit.vintage", module = "junit-vintage-engine")
    }
    testImplementation("org.springframework.security:spring-security-test")
    testImplementation("org.jetbrains.kotlin:kotlin-test-junit5:1.4.10")
    testImplementation("io.mockk:mockk:1.10.2")
    testImplementation("com.ninja-squad:springmockk:2.0.3")
}

导致该异常的原因是什么,我该如何解决?如果需要更多上下文,请告诉我。

编辑:当 CircleCI 使用图像 cimg/openjdk:8.0 运行测试时,不会发生相同的异常

编辑 2:添加了 DBSequenceDBSequenceRepo 的定义

@Document(collection = "dbSequences")
data class DBSequence(
    @Id var name: String,
    var nextVal: Long
) {

    override fun equals(other: Any?): Boolean {
        if (this === other) return true
        if (javaClass != other?.javaClass) return false

        other as DBSequence

        if (name != other.name) return false

        return true
    }

    override fun hashCode(): Int {
        return name.hashCode()
    }
}

interface DBSequencesRepo : MongoRepository<DBSequence, String>

【问题讨论】:

  • 请添加DBSequencesRepo的定义
  • @sedovav 完成。实际的 repo 由 Spring 自动创建

标签: spring-boot kotlin mockk


【解决方案1】:

有一个与问题相关的open issue in mockk。该错误在 JVM 变体的子集上重现。我想您在本地安装了这样的 JVM 之一。作为一种解决方法,您可以尝试在本地安装不同的 JVM 发行版。根据上面的链接,“AdoptOpenJDK: 1.8.0_222 热点”似乎没问题。

【讨论】:

  • 看起来问题出在 OpenJ9 上,这正是我使用的!安装了 Hotspot JVM 并开始运行测试。
【解决方案2】:

我们今天在本地机器上遇到了类似的问题。我们正在尝试 MockK 与 vert.x 和 Kotlin 的后端服务。

我们的开发机器是使用 OpenJDK 11.0.9 的 MacO,出于某种奇怪的原因,有时运行没有问题,有时在测试超时出现以下消息之前保持活动状态:

per (java.base@9/Class.java:1457)
    at java/lang/Class.getMethod (java.base@9/Class.java:1361)
    at java/lang/Object.hashCode (java.base@9/Object.java:122)
    at java/util/HashMap.hash (java.base@9/HashMap.java:339)
    at java/util/HashMap.get (java.base@9/HashMap.java:552)
    at jdk/internal/reflect/Reflection.filterMethods (java.base@9/Reflection.java:276)
    at java/lang/Class.getMethodHelper (java.base@9/Class.java:1457)
    at java/lang/Class.getMethod (java.base@9/Class.java:1361)
    at java/lang/Object.hashCode (java.base@9/Object.java:122)
    at java/util/HashMap.hash (java.base@9/HashMap.java:339)
    at java/util/HashMap.get (java.base@9/HashMap.java:552)
    at jdk/internal/reflect/Reflection.filterMethods (java.base@9/Reflection.java:276)
    at java/lang/Class.getMethodHelper (java.base@9/Class.java:1457)
    at java/lang/Class.getMethod (java.base@9/Class.java:1361)
    at java/lang/Object.hashCode (java.base@9/Object.java:122)
    at java/util/HashMap.hash (java.base@9/HashMap.java:339)
    at java/util/HashMap.get (java.base@9/HashMap.java:552)
    at jdk/internal/reflect/Reflection.filterMethods (java.base@9/Reflection.java:276)
    at java/lang/Class.getMethodHelper (java.base@9/Class.java:1457)
    at java/lang/Class.getMethod (java.base@9/Class.java:1361)
    at java/lang/Object.hashCode (java.base@9/Object.java:122)
    at java/util/HashMap.hash (java.base@9/HashMap.java:339)
    at java/util/HashMap.get (java.base@9/HashMap.java:552)
    at jdk/internal/reflect/Reflection.filterMethods (java.base@9/Reflection.java:276)
    at java/lang/Class.getMethodHelper (java.base@9/Class.java:1457)
    at java/lang/Class.getMethod (java.base@9/Class.java:1361)
    at java/lang/Object.hashCode (java.base@9/Object.java:122)
    at java/util/HashMap.hash (java.base@9/HashMap.java:339)
    at java/util/HashMap.get (java.base@9/HashMap.java:552)
    at jdk/internal/reflect/Reflection.filterMethods (java.base@9/Reflection.java:276)
    at java/lang/Class.getMethodHelper (java.base@9/Class.java:1457)
    at java/lang/Class.getMethod (java.base@9/Class.java:1361)
    at java/lang/Object.hashCode (java.base@9/Object.java:122)
    at java/util/HashMap.hash (java.base@9/HashMap.java:339)
    at java/util/HashMap.get (java.base@9/HashMap.java:552)
    at jdk/internal/reflect/Reflection.filterMethods (java.base@9/Reflection.java:276)
    at java/lang/Class.getMethodHelper (java.base@9/Class.java:1457)
    at java/lang/Class.getMethod (java.base@9/Class.java:1361)
    at java/lang/Object.hashCode (java.base@9/Object.java:122)
    at java/util/HashMap.hash (java.base@9/HashMap.java:339)
    at java/util/HashMap.get (java.base@9/HashMap.java:552)
    at jdk/internal/reflect/Reflection.filterMethods (java.base@9/Reflection.java:276)
    at java/lang/Class.getMethodHelper (java.base@9/Class.java:1457)
    at java/lang/Class.getMethod (java.base@9/Class.java:1361)
    at java/lang/Object.hashCode (java.base@9/Object.java:122)
    at java/util/HashMap.hash (java.base@9/HashMap.java:339)
    at java/util/HashMap.get (java.base@9/HashMap.java:552)
    at jdk/internal/reflect/Reflection.filterMethods (java.base@9/Reflection.java:276)
    at java/lang/Class.getMethodHelper (java.base@9/Class.java:1457)
    at java/lang/Class.getMethod (java.base@9/Class.java:1361)
    at java/lang/Object.hashCode (java.base@9/Object.java:122)
    at java/util/HashMap.hash (java.base@9/HashMap.java:339)
    at java/util/HashMap.get (java.base@9/HashMap.java:552)
    at jdk/internal/reflect/Reflection.filterMethods (java.base@9/Reflection.java:276)
    at java/lang/Class.getMethodHelper (java.base@9/Class.java:1457)
    at java/lang/Class.getMethod (java.base@9/Class.java:1361)
    at java/lang/Object.hashCode (java.base@9/Object.java:122)
    at java/util/HashMap.hash (java.base@9/HashMap.java:339)
    at java/util/HashMap.get (java.base@9/HashMap.java:552)
    at jdk/internal/reflect/Reflection.filterMethods (java.base@9/Reflection.java:276)
    at java/lang/Class.getMethodHelper (java.base@9/Class.java:1457)
    at java/lang/Class.getMethod (java.base@9/Class.java:1361)
    at java/lang/Object.hashCode (java.base@9/Object.java:122)
    at java/util/HashMap.hash (java.base@9/HashMap.java:339)
    at java/util/HashMap.get (java.base@9/HashMap.java:552)
    at jdk/internal/reflect/Reflection.filterMethods (java.base@9/Reflection.java:276)
    at java/lang/Class.getMethodHelper (java.base@9/Class.java:1457)
    at java/lang/Class.getMethod (java.base@9/Class.java:1361)
    at java/lang/Object.hashCode (java.base@9/Object.java:122)
    at java/util/HashMap.hash (java.base@9/HashMap.java:339)
    at java/util/HashMap.get (java.base@9/HashMap.java:552)
    at jdk/internal/

当我们在 Idea 项目设置和 Gradle 中将 JDK 设置为 8.* 时,会出现一个测试通过,一个测试失败并出现与上图相同的错误的情况。

我不是 MockK 库的专家,但我很想将它与 mockito-kotlin 进行比较。 当与最新版本的 JDK 一起使用时,IMO 库在反射方面存在一些问题。

【讨论】:

    【解决方案3】:

    对我来说,我收到以下错误:

    at java/lang/Class.getMethod (java.base@9/Class.java:1361)
        at java/lang/Object.hashCode (java.base@9/Object.java:122)
        at java/util/HashMap.hash (java.base@9/HashMap.java:339)
        at java/util/HashMap.get (java.base@9/HashMap.java:552)
        at jdk/internal/reflect/Reflection.filterMethods (java.base@9/Reflection.java:276)
        at java/lang/Class.getMethodHelper (java.base@9/Class.java:1457)
        at java/lang/Class.getMethod (java.base@9/Class.java:1361)
        at java/lang/Object.hashCode (java.base@9/Object.java:122)
        at java/util/HashMap.hash (java.base@9/HashMap.java:339)
        at java/util/HashMap.get (java.base@9/HashMap.java:552)
        at jdk/internal/reflect/Reflection.filterMethods (java.base@9/Reflection.java:276)
        at java/lang/Class.getMethodHelper (java.base@9/Class.java:1457)
        at java/lang/Class.getMethod (java.base@9/Class.java:1361)
        at java/lang/Object.hashCode (java.base@9/Object.java:122)
        at java/util/HashMap.hash (java.base@9/HashMap.java:339)
        at java/util/HashMap.get (java.base@9/HashMap.java:552)`
    

    事实证明,mockK 库无法在某些版本的 Java 11 上运行(尤其是 11.0.10.j9-adpt

    如果您使用的是 sdkman,请使用 11.0.10.hs-adpt 版本

    | | 11.0.10.j9 | adpt | | 11.0.10.j9-adpt
    | &gt;&gt;&gt; | 11.0.10.hs | adpt | installed | 11.0.10.hs-adpt

    【讨论】:

      猜你喜欢
      • 2016-12-16
      • 1970-01-01
      • 2019-11-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-02-08
      • 2015-08-24
      相关资源
      最近更新 更多