Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Spyk'ed object can't be unmocked which leads to OutOfMemoryError #1013

Closed
bakomchik opened this issue Dec 30, 2022 · 5 comments
Closed

Spyk'ed object can't be unmocked which leads to OutOfMemoryError #1013

bakomchik opened this issue Dec 30, 2022 · 5 comments

Comments

@bakomchik
Copy link

Expected Behavior

unmock(spyk()) -- works
No java.lang.OutOfMemoryError: Java heap space error occurred.

Current Behavior

java.lang.OutOfMemoryError: Java heap space occurs

unmock(spyk()) -- does not unmock spyk'ed object

Failure Information (for bugs)

Context

We have a lot of SpringBoot tests .
We annotated @Lazy bean with @SpykBean in our TestCaseBase class
And sometimes new spring context created and bean get spyked again and it leads to OutOfMemoryError
because spiked object can't be unmocked/unspyked

  • MockK version: implementation("io.mockk:mockk:1.13.3")

  • OS: Darwin 21.6.0 Darwin Kernel Version 21.6.0: Thu Sep 29 20:13:56 PDT 2022; root:xnu-8020.240.7~1/RELEASE_ARM64_T6000 arm64

  • Kotlin version: 1.7.21

  • JDK version: openjdk 11.0.16.1 2022-08-12 OpenJDK Runtime Environment Homebrew (build 11.0.16.1+0) OpenJDK 64-Bit Server VM Homebrew (build 11.0.16.1+0, mixed mode)

  • Type of test: unit test

Minimal reproducible code (the gist of this issue)

// -----------------------[ GRADLE DEFINITIONS ] -----------------------
dependencies {
    testImplementation(kotlin("test"))
    implementation("io.mockk:mockk:1.13.3")
}

tasks.test {
    useJUnitPlatform()
}

tasks.withType<KotlinCompile> {
    kotlinOptions.jvmTarget = "1.8"
}

application {
    mainClass.set("MainKt")
}
// -----------------------[ YOUR CODE STARTS HERE ] -----------------------


fun main(args: Array<String>) {
    (0..1000).forEach {
        val spyk = spyk(LazySpringBeanWhichHoldsReferenceForBeanFactory(ByteArray(10 * 1024 * 1024)))
        every { spyk.doSmth() } returns "Wow"
        spyk.doSmth();
        clearMocks(spyk)
        unmockkObject(spyk)
    }
}

class LazySpringBeanWhichHoldsReferenceForBeanFactory(val beanFactory: ByteArray){
    fun doSmth():String{
            return "Smth"
    }
}
@bakomchik
Copy link
Author

Path to gc roots
Снимок экрана 2022-12-30 в 18 02 50
The object kept by these strong references an can't be collected by gc
image

@bakomchik
Copy link
Author

Looks like original object can't be collected by GC and removed from all maps due to strong reference via path
Снимок экрана 2023-01-04 в 14 12 38

bakomchik pushed a commit to bakomchik/mockk that referenced this issue Jan 4, 2023

Verified

This commit was signed with the committer’s verified signature.
Byron Sebastian Thiel
…lable to GC
@bakomchik
Copy link
Author

I've created pull request https://github.com/mockk/mockk/pull/1018/files

@bakomchik
Copy link
Author

I found that mock(proxy) objects ,that supposed to be collected by gc, can't be collected despite the fact that weak reference used for storing these objects in WeakMockHandlersMap, because of these proxy objects are strongly reachable via dispose routine

Raibaz added a commit that referenced this issue Jan 15, 2023

Verified

This commit was signed with the committer’s verified signature.
Byron Sebastian Thiel
#1013 uncouple proxy objects from cancellable to make proxy available…
@mabwah-arista
Copy link

mabwah-arista commented Jul 5, 2023

It seems the fix for #997 undid this, as now I'm seeing memory leaks due to spy objects not being GCed once cleared. There must be a way to allow these objects to be GCed when calling clearAllMocks while not having them disappear while they're still needed.

@Raibaz do you have any recommendations? Also worth noting that the unit test added in #1018 doesn't actually detect it as it's broken but the tests are passing (I assume).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants