mockk: Bug: StackOverflowError in case of complex annotation checks involving HashMap calls
Expected Behavior
Class should be mocked w/o errors
Current Behavior
Stackoverflow Exception stops execution
Failure Information (for bugs)
I try to mockk a class which has a default ctor with several interfaces. The ‘to be mocked’ class itself is a Spring Component (annotated), the interfaces for the ctor are Spring Repositories (annotated). Running the tests produces the mentioned StackOverflowError. Commenting out the mockk<> removes the error.
Steps to Reproduce
Project with Mockk (1.9.3), Spring Boot(2.1.6)/Framework(5.1.8), Spring Mongo(2.1.9) and Junit (4.12).
See code below.
Context
Please provide any relevant information about your setup. This is important in case the issue is not reproducible except for under certain conditions.
- MockK version: 1.9.3
- OS: Windows 10 1903
- Kotlin version: 1.3.41
- JDK version: 1.8
- JUnit version: 4.12
- Type of test: unit test
Failure Logs
Stack trace
Exception in thread "main" java.lang.StackOverflowError
at java.util.concurrent.ConcurrentHashMap.get(ConcurrentHashMap.java:936)
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:1261)
at java.lang.Class.getMethod(Class.java:1187)
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:1261)
at java.lang.Class.getMethod(Class.java:1187)
---- lines repeat a lot -----
at java.lang.Object.hashCode(Object.java:119)
at java.util.HashMap.hash(HashMap.java:339)
at java.util.LinkedHashMap.get(LinkedHashMap.java:440)
at java.lang.Class.getAnnotation(Class.java:2181)
at java.lang.Class.isAnnotationPresent(Class.java:2589)
at org.junit.runner.notification.RunNotifier.wrapIfNotThreadSafe(RunNotifier.java:50)
at org.junit.runner.notification.RunNotifier.removeListener(RunNotifier.java:42)
at org.junit.runner.JUnitCore.removeListener(JUnitCore.java:161)
at org.junit.runner.JUnitCore.run(JUnitCore.java:140)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
Exception in thread "Thread-5" java.lang.StackOverflowError
// -----------------------[ YOUR STACK TRACE ENDS HERE ] -----------------------
Minimal reproducible code (the gist of this issue)
// -----------------------[ GRADLE DEFINITIONS ] -----------------------
dependencies {
implementation(kotlin("stdlib-jdk8"))
implementation(kotlin("reflect"))
implementation("org.springframework.boot:spring-boot-starter:2.1.6.RELEASE")
implementation("org.springframework.boot:spring-boot-starter-data-mongodb:2.1.9.RELEASE")
testImplementation("io.mockk:mockk:1.9.3")
testImplementation(kotlin("test"))
testImplementation(kotlin("test-junit"))
testImplementation("org.springframework.boot:spring-boot-starter-test:2.1.6.RELEASE")
testImplementation("junit:junit:4.12")
}
// -----------------------[ YOUR CODE STARTS HERE ] -----------------------
package io.mockk.gh
import io.mockk.mockk
import org.junit.Test
import org.springframework.beans.factory.annotation.Value
import org.springframework.data.mongodb.repository.MongoRepository
import org.springframework.stereotype.Component
import org.springframework.stereotype.Repository
interface AnotherInterface1
interface AnotherInterface2
class PersistencyClass1
class PersistencyClass2
@Repository
interface Repo1 : MongoRepository<PersistencyClass1, String>, AnotherInterface1
@Repository
interface Repo2 : MongoRepository<PersistencyClass2, String>, AnotherInterface2
@Component
class ToBeMocked(
private val repo1: Repo1,
private val repo2: Repo2,
@Value("\${number:1000}") private val someNumber: Long)
class MockkTest {
private val mockedObject = mockk<ToBeMocked>() //here it happens
@Test
fun dummyTst() {
//no code needed to reproduce
}
}
// -----------------------[ YOUR CODE ENDS HERE ] -----------------------
About this issue
- Original URL
- State: open
- Created 5 years ago
- Reactions: 18
- Comments: 17
Commits related to this issue
- Disable OpenJ9 due to mockk/mockk#337 — committed to Protelis/Protelis-Demo by DanySK 5 years ago
- Re-enable OpenJ9 This will get merged once mockk/mockk#337 is fixed. — committed to Protelis/Protelis-Demo by DanySK 4 years ago
- Re-enable OpenJ9 This will get merged once mockk/mockk#337 is fixed. — committed to Protelis/Protelis-Demo by DanySK 4 years ago
- Drop Mockk and use Mockito-Kt due to mockk/mockk#337 — committed to DanySK/upgradle by DanySK 4 years ago
- Re-enable OpenJ9 This will get merged once mockk/mockk#337 is fixed. — committed to Protelis/Protelis-Demo by DanySK 4 years ago
- Re-enable OpenJ9 This will get merged once mockk/mockk#337 is fixed. — committed to Protelis/Protelis-Demo by DanySK 4 years ago
- Re-enable OpenJ9 This will get merged once mockk/mockk#337 is fixed. — committed to Protelis/Protelis-Demo by DanySK 4 years ago
- Re-enable OpenJ9 This will get merged once mockk/mockk#337 is fixed. — committed to Protelis/Protelis-Demo by DanySK 4 years ago
- Re-enable OpenJ9 This will get merged once mockk/mockk#337 is fixed. — committed to Protelis/Protelis-Demo by DanySK 4 years ago
- Re-enable OpenJ9 This will get merged once mockk/mockk#337 is fixed. — committed to Protelis/Protelis-Demo by DanySK 4 years ago
Ok, so i did some research and tried out some stuff. Turns out it is because of the installed JDK. I used AdoptOpenJDK 1.8.0_212 openJ9 wich leads to the error.
I then tried out some configurations and came up with following list:
AdoptOpenJDK: 1.8.0_212 openJ9 -> FAIL AdoptOpenJDK: 1.8.0_222 hotspot -> OK AdoptOpenJDK: 1.8.0_222 openJ9 -> FAIL AdoptOpenJDK: 11.0.1+13 openJ9 -> OK AdoptOpenJDK: 11.0.4+11 openJ9 -> FAIL AdoptOpenJDK: 11.0.4+11 hotspot -> OK
Overall the hotspot variants are working. I leave it up to Mockk team whether you want to look into supporting openJ9. I switched to hotspot for now.
So long, Felix
Is there any plan to fix this ? I have this same issue with OpenJ9 13
sdkman users should use version 11.0.10.hs-adpt for java 11 support - FYI as this stackoverflow happens in other versions too
Hi, I also facing the same issue when mocking Spring beans by @MockkBean (springmockk). It indeed fail only on openJ9, hotspot is ok. Another observation is that it’s failing only on CGLIB-based proxies. In case of injecting Interface (by default Spring will create JDK proxy) everything is ok.
This is unrelated to Jacoco, this is the minimal reproduction case I could come up with: