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

Unit tests fail after kover is added to project #730

Closed
josemssilva opened this issue Jan 29, 2025 · 5 comments
Closed

Unit tests fail after kover is added to project #730

josemssilva opened this issue Jan 29, 2025 · 5 comments
Assignees
Labels
Bug Bug issue type S: waiting for clarification Status: additional information required to proceed

Comments

@josemssilva
Copy link

Describe the bug
After adding kover to the project, unit tests started failing for unexpected reasons. The issue seems related to MockK, however it isn't clear what is causing it, and it only happens once kover is integrated.

Errors

java.lang.UnsupportedOperationException: class redefinition failed: attempted to change the schema (add/remove fields)
	at java.instrument/sun.instrument.InstrumentationImpl.retransformClasses0(Native Method)
	at java.instrument/sun.instrument.InstrumentationImpl.retransformClasses(InstrumentationImpl.java:169)
	at io.mockk.proxy.jvm.transformation.JvmInlineInstrumentation.retransform(JvmInlineInstrumentation.kt:28)
	at io.mockk.proxy.common.transformation.RetransformInlineInstrumentation$doCancel$1.invoke(RetransformInlineInstrumentation.kt:38)
	at io.mockk.proxy.common.transformation.RetransformInlineInstrumentation$doCancel$1.invoke(RetransformInlineInstrumentation.kt:32)
	at io.mockk.proxy.common.transformation.ClassTransformationSpecMap.applyTransformation(ClassTransformationSpecMap.kt:41)
	at io.mockk.proxy.common.transformation.RetransformInlineInstrumentation.doCancel(RetransformInlineInstrumentation.kt:32)
	at io.mockk.proxy.common.transformation.RetransformInlineInstrumentation.access$doCancel(RetransformInlineInstrumentation.kt:6)
	at io.mockk.proxy.common.transformation.RetransformInlineInstrumentation$execute$1$1.invoke(RetransformInlineInstrumentation.kt:17)
	at io.mockk.proxy.common.transformation.RetransformInlineInstrumentation$execute$1$1.invoke(RetransformInlineInstrumentation.kt:17)
	at io.mockk.proxy.common.CancelableResult.cancel(CancelableResult.kt:22)
	at io.mockk.proxy.common.CancelableResult$alsoOnCancel$1.invoke(CancelableResult.kt:30)
	at io.mockk.proxy.common.CancelableResult$alsoOnCancel$1.invoke(CancelableResult.kt:29)
	at io.mockk.proxy.common.CancelableResult.cancel(CancelableResult.kt:22)
	at io.mockk.impl.instantiation.JvmConstructorMockFactory$ConstructorInvocationHandler.doCancel(JvmConstructorMockFactory.kt:242)
	at io.mockk.impl.instantiation.JvmConstructorMockFactory$ConstructorInvocationHandler.access$doCancel(JvmConstructorMockFactory.kt:155)
	at io.mockk.impl.instantiation.JvmConstructorMockFactory$ConstructorInvocationHandler$push$2.invoke(JvmConstructorMockFactory.kt:217)
	at io.mockk.impl.instantiation.JvmConstructorMockFactory$ConstructorInvocationHandler$push$2.invoke(JvmConstructorMockFactory.kt:216)
	at io.mockk.MockKCancellationRegistry$RegistryPerType.cancelAll(API.kt:2440)
	at io.mockk.MockKCancellationRegistry.cancelAll(API.kt:2469)

Expected behavior
Tests shouldn't fail, as it was happening prior to introducing kover.

Reproducer
Only happens in test classes, when unmockkAll() is called.

Reports

Environment

  • Kover Gradle Plugin version: 0.9.1
  • Gradle version: 8.6
  • Kotlin project type: Kotlin/Android
  • Coverage Toolset (if customized in build script): -
  • Other context important for this bug: -
@josemssilva josemssilva added Bug Bug issue type S: untriaged Status: issue reported but unprocessed labels Jan 29, 2025
@shanshin
Copy link
Collaborator

shanshin commented Feb 4, 2025

Hi,
is this a complete error stack trace?

Don't you have a small production project? Due to this error, it is difficult to understand which instrumentation class is causing the error.

@shanshin shanshin added S: waiting for clarification Status: additional information required to proceed and removed S: untriaged Status: issue reported but unprocessed labels Feb 4, 2025
@josemssilva
Copy link
Author

Full stacktrace:

java.lang.UnsupportedOperationException: class redefinition failed: attempted to change the schema (add/remove fields)
	at java.instrument/sun.instrument.InstrumentationImpl.retransformClasses0(Native Method)
	at java.instrument/sun.instrument.InstrumentationImpl.retransformClasses(InstrumentationImpl.java:169)
	at io.mockk.proxy.jvm.transformation.JvmInlineInstrumentation.retransform(JvmInlineInstrumentation.kt:28)
	at io.mockk.proxy.common.transformation.RetransformInlineInstrumentation$doCancel$1.invoke(RetransformInlineInstrumentation.kt:38)
	at io.mockk.proxy.common.transformation.RetransformInlineInstrumentation$doCancel$1.invoke(RetransformInlineInstrumentation.kt:32)
	at io.mockk.proxy.common.transformation.ClassTransformationSpecMap.applyTransformation(ClassTransformationSpecMap.kt:41)
	at io.mockk.proxy.common.transformation.RetransformInlineInstrumentation.doCancel(RetransformInlineInstrumentation.kt:32)
	at io.mockk.proxy.common.transformation.RetransformInlineInstrumentation.access$doCancel(RetransformInlineInstrumentation.kt:6)
	at io.mockk.proxy.common.transformation.RetransformInlineInstrumentation$execute$1$1.invoke(RetransformInlineInstrumentation.kt:17)
	at io.mockk.proxy.common.transformation.RetransformInlineInstrumentation$execute$1$1.invoke(RetransformInlineInstrumentation.kt:17)
	at io.mockk.proxy.common.CancelableResult.cancel(CancelableResult.kt:22)
	at io.mockk.proxy.common.CancelableResult$alsoOnCancel$1.invoke(CancelableResult.kt:30)
	at io.mockk.proxy.common.CancelableResult$alsoOnCancel$1.invoke(CancelableResult.kt:29)
	at io.mockk.proxy.common.CancelableResult.cancel(CancelableResult.kt:22)
	at io.mockk.impl.instantiation.JvmConstructorMockFactory$ConstructorInvocationHandler.doCancel(JvmConstructorMockFactory.kt:242)
	at io.mockk.impl.instantiation.JvmConstructorMockFactory$ConstructorInvocationHandler.access$doCancel(JvmConstructorMockFactory.kt:155)
	at io.mockk.impl.instantiation.JvmConstructorMockFactory$ConstructorInvocationHandler$push$2.invoke(JvmConstructorMockFactory.kt:217)
	at io.mockk.impl.instantiation.JvmConstructorMockFactory$ConstructorInvocationHandler$push$2.invoke(JvmConstructorMockFactory.kt:216)
	at io.mockk.MockKCancellationRegistry$RegistryPerType.cancelAll(API.kt:2440)
	at io.mockk.MockKCancellationRegistry.cancelAll(API.kt:2469)
	at packagename.classname.finish(TestClass.kt:857)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:569)
	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)
	at org.junit.internal.runners.statements.RunAfters.invokeMethod(RunAfters.java:46)
	at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:33)
	at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
	at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)
	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63)
	at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
	at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
	at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
	at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.runTestClass(JUnitTestClassExecutor.java:112)
	at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.execute(JUnitTestClassExecutor.java:58)
	at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.execute(JUnitTestClassExecutor.java:40)
	at org.gradle.api.internal.tasks.testing.junit.AbstractJUnitTestClassProcessor.processTestClass(AbstractJUnitTestClassProcessor.java:60)
	at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.processTestClass(SuiteTestClassProcessor.java:52)
	at jdk.internal.reflect.GeneratedMethodAccessor88.invoke(Unknown Source)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:569)
	at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:36)
	at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
	at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:33)
	at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:94)
	at jdk.proxy1/jdk.proxy1.$Proxy2.processTestClass(Unknown Source)
	at org.gradle.api.internal.tasks.testing.worker.TestWorker$2.run(TestWorker.java:176)
	at org.gradle.api.internal.tasks.testing.worker.TestWorker.executeAndMaintainThreadName(TestWorker.java:129)
	at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:100)
	at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:60)
	at org.gradle.process.internal.worker.child.ActionExecutionWorker.execute(ActionExecutionWorker.java:56)
	at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:113)
	at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:65)
	at worker.org.gradle.process.internal.worker.GradleWorkerMain.run(GradleWorkerMain.java:69)
	at worker.org.gradle.process.internal.worker.GradleWorkerMain.main(GradleWorkerMain.java:74)

It's really odd, because it only fails when running via CLI. Also, when doing sequential tests it only fails the first run (then it fails again after a ./gradlew clean).

@shanshin
Copy link
Collaborator

Is your project multi-module?

You may limit instrumented classes in all projects.
To do this, specify this setting in each project:

kover {
    currentProject {
        instrumentation {
            excludedClasses.add("io.mockk.*")
        }
    }
}

If it doesn't help, try to instrument the classes of your application only. To do this, specify the largest package in which all your classes are exactly located (in include filter)

kover {
    currentProject {
        instrumentation {
            includedClasses.add("com.myapplication.*")
        }
    }
}

@josemssilva
Copy link
Author

Yes, multi-module.

None of the solutions worked, unfortunately. However, I was able to solve it by replacing unmockkAll() with unmockkStatic() for each of the mockkStatic() previously performed. I still can't find a reason for it to fail with the former, and it was odd that it only happened after integration Kover, so I thought it could be an issue with the tool.

Sorry for the mess, I believe we can now close this.

@shanshin
Copy link
Collaborator

OK, but please reopen the issue if you create a small stable reproducer.

@shanshin shanshin closed this as not planned Won't fix, can't repro, duplicate, stale Feb 13, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug Bug issue type S: waiting for clarification Status: additional information required to proceed
Projects
None yet
Development

No branches or pull requests

2 participants