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

1.12.5 fails to every certain java classes #868

Closed
vojkny opened this issue Jul 28, 2022 · 38 comments · Fixed by #922
Closed

1.12.5 fails to every certain java classes #868

vojkny opened this issue Jul 28, 2022 · 38 comments · Fixed by #922

Comments

@vojkny
Copy link

vojkny commented Jul 28, 2022

I created a demo/minimal project here:

https://gitlab.com/knyttl/mockkdemo/-/tree/main

You can see the CI build with test failure here:

https://gitlab.com/knyttl/mockkdemo/-/jobs/2782097977

Feel free to change the build.gradle.kts mockk version to 1.12.4 which will test correctly.

Expected Behavior

The tests shouldn't fail.

Current Behavior

The test fails with:

kotlin.reflect.jvm.internal.KotlinReflectionInternalError: Unresolved class: class org.elasticsearch.search.sort.SortOrder$1

As you can see in the CI run mentioned above.

Failure Information (for bugs)

See CI run mentioned above.

Steps to Reproduce

See the source code mentioned above. Feel free to change the version to 1.12.4 which will build correctly.

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.12.5
  • Kotlin version: 1.7.10
  • JDK version: 17

Minimal reproducible code (the gist of this issue)

import io.mockk.every
import io.mockk.mockk
import org.elasticsearch.search.sort.SortOrder
import org.junit.jupiter.api.Test

class MockkDemo {
    @Test
    fun testMockk() {
        val repo = mockk<TestClass>()
        every { repo.getSchedules() } returns "Foo"
    }
}

class TestClass {
    fun getSchedules(sortOrder: SortOrder = SortOrder.ASC): String =
        sortOrder.toString()
}
@ascheja
Copy link

ascheja commented Jul 28, 2022

I've encountered a very similar issue with 1.12.5, though purely with Kotlin. see https://github.com/ascheja/KotlinReflectionInternalError-reproducer-mockk. In my case there is an issue with a class not being there for a lambda, but the issue only appears in certain scenarios (i.e. with an anonymous class or different surrounding code it works just fine).

I suspect it could be related to https://youtrack.jetbrains.com/issue/KT-41373, but I'm not sure.

@vojkny
Copy link
Author

vojkny commented Jul 28, 2022

I guess this is not related as SortOrder (which fails) is not anonymous and also this works with the same Kotlin version, but different mockk version.

@TZanke
Copy link

TZanke commented Jul 29, 2022

Same error on my ci-system after upgrading to 1.12.5. Reverted Back to 1.12.3

@takanuva15
Copy link

I've gotten a similar error when upgrading to 1.12.5. I reverted back to 1.12.4 and it's working again for me.

The error output in my case:

Unresolved class: class de.nordgedanken.auto_hotkey.ide.actions.AhkCompileToExeActionTest$$Lambda$1506/0x0000000100ce8840
kotlin.reflect.jvm.internal.KotlinReflectionInternalError: Unresolved class: class de.nordgedanken.auto_hotkey.ide.actions.AhkCompileToExeActionTest$$Lambda$1506/0x0000000100ce8840
	at kotlin.reflect.jvm.internal.KClassImpl.reportUnresolvedClass(KClassImpl.kt:328)
	at kotlin.reflect.jvm.internal.KClassImpl.access$reportUnresolvedClass(KClassImpl.kt:44)
	at kotlin.reflect.jvm.internal.KClassImpl$Data$descriptor$2.invoke(KClassImpl.kt:56)
	at kotlin.reflect.jvm.internal.KClassImpl$Data$descriptor$2.invoke(KClassImpl.kt:48)
	at kotlin.reflect.jvm.internal.ReflectProperties$LazySoftVal.invoke(ReflectProperties.java:93)
	at kotlin.reflect.jvm.internal.ReflectProperties$Val.getValue(ReflectProperties.java:32)
	at kotlin.reflect.jvm.internal.KClassImpl$Data.getDescriptor(KClassImpl.kt:48)
	at kotlin.reflect.jvm.internal.KClassImpl.getDescriptor(KClassImpl.kt:182)
	at kotlin.reflect.jvm.internal.KClassImpl.isValue(KClassImpl.kt:290)
	at io.mockk.ValueClassSupportKt.isValue_safe(ValueClassSupport.kt:62)
	at io.mockk.ValueClassSupportKt.getBoxedValue(ValueClassSupport.kt:19)
	at io.mockk.proxy.jvm.advice.Interceptor.call(Interceptor.kt:22)
	at com.intellij.ide.impl.HeadlessDataManager.getDataContext(HeadlessDataManager.java:103)
	at com.intellij.testFramework.TestActionEvent.<init>(TestActionEvent.java:36)
	at com.intellij.testFramework.fixtures.impl.CodeInsightTestFixtureImpl.testAction(CodeInsightTestFixtureImpl.java:885)
	at de.nordgedanken.auto_hotkey.ide.actions.AhkCompileToExeActionTest.test error balloon shown if compilation fails(AhkCompileToExeActionTest.kt:73)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:566)
	at junit.framework.TestCase.runTest(TestCase.java:177)
	at com.intellij.testFramework.UsefulTestCase.lambda$runBare$11(UsefulTestCase.java:531)
	at com.intellij.testFramework.UsefulTestCase.lambda$wrapTestRunnable$13(UsefulTestCase.java:552)
	at com.intellij.testFramework.UsefulTestCase.runTestRunnable(UsefulTestCase.java:452)
	at com.intellij.testFramework.fixtures.BasePlatformTestCase.runTestRunnable(BasePlatformTestCase.java:106)
	at com.intellij.testFramework.UsefulTestCase.defaultRunBare(UsefulTestCase.java:468)
	at com.intellij.testFramework.UsefulTestCase.lambda$runBare$12(UsefulTestCase.java:539)
	at com.intellij.testFramework.EdtTestUtil.lambda$runInEdtAndWait$1(EdtTestUtil.java:40)
	at java.desktop/java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:303)
	at java.desktop/java.awt.EventQueue.dispatchEventImpl(EventQueue.java:770)
	at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:721)
	at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:715)
	at java.base/java.security.AccessController.doPrivileged(Native Method)
	at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:85)
	at java.desktop/java.awt.EventQueue.dispatchEvent(EventQueue.java:740)
	at com.intellij.ide.IdeEventQueue.dispatchEvent(IdeEventQueue.java:393)
	at java.desktop/java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:203)
	at java.desktop/java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:124)
	at java.desktop/java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:113)
	at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:109)
	at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
	at java.desktop/java.awt.EventDispatchThread.run(EventDispatchThread.java:90)

Unfortunately it's difficult for me to generate an MVE since I am running mockk tests as part of a plugin for the IntelliJ IDE, so the IntelliJ runtime is a dependency during the test. Hopefully someone else has a more lightweight codebase where they could reproduce the issue.

(If you're feeling adventurous, you could clone https://github.com/Nordgedanken/intellij-autohotkey, upgrade mockk to 1.12.5, and you'd see the error occur when running tests in AhkCompileToExeActionTest.kt)

@qoomon
Copy link
Contributor

qoomon commented Jul 30, 2022

Might be fixed by #872

@vojkny
Copy link
Author

vojkny commented Jul 30, 2022

When will you release it?

@realjenius
Copy link

I just tested Mockk 1.12.7 which I believe has #872 and I'm still getting this error in my code as well.

@vojkny
Copy link
Author

vojkny commented Aug 23, 2022

I confirm that the problem persists. I updated the demo:

@qoomon
Copy link
Contributor

qoomon commented Aug 23, 2022

Seems to be a dedicated problem for java enum classes that implements an interface.

@realjenius
Copy link

My case failed with something other than an enum - I was trying to use Collections.enumeration(...) to generate an enumeration for HttpServletRequest.getHeaderNames() with this failure:

kotlin.reflect.jvm.internal.KotlinReflectionInternalError: Unresolved class: class java.util.Collections$3
      at kotlin.reflect.jvm.internal.KClassImpl.reportUnresolvedClass(KClassImpl.kt:328)
      at kotlin.reflect.jvm.internal.KClassImpl.access$reportUnresolvedClass(KClassImpl.kt:44)
      at kotlin.reflect.jvm.internal.KClassImpl$Data$descriptor$2.invoke(KClassImpl.kt:56)
      at kotlin.reflect.jvm.internal.KClassImpl$Data$descriptor$2.invoke(KClassImpl.kt:48)
      at kotlin.reflect.jvm.internal.ReflectProperties$LazySoftVal.invoke(ReflectProperties.java:93)
      at kotlin.reflect.jvm.internal.ReflectProperties$Val.getValue(ReflectProperties.java:32)
      at kotlin.reflect.jvm.internal.KClassImpl$Data.getDescriptor(KClassImpl.kt:48)
      at kotlin.reflect.jvm.internal.KClassImpl.getDescriptor(KClassImpl.kt:182)
      at kotlin.reflect.jvm.internal.KClassImpl.isValue(KClassImpl.kt:290)
      at io.mockk.ValueClassSupportKt.isValue_safe(ValueClassSupport.kt:62)
      at io.mockk.ValueClassSupportKt.getBoxedValue(ValueClassSupport.kt:19)
      at io.mockk.proxy.jvm.advice.Interceptor.call(Interceptor.kt:22)
      at io.mockk.proxy.jvm.advice.BaseAdvice.handle(BaseAdvice.kt:42)
      at io.mockk.proxy.jvm.advice.jvm.JvmMockKProxyInterceptor.interceptNoSuper(JvmMockKProxyInterceptor.java:45)
      at javax.servlet.http.HttpServletRequest$Subclass0.getHeaderNames(Unknown Source)

The mock stubbing looks like this:

every { request.headerNames } returns Collections.enumeration(setOf("a", "b", "c"))

@qoomon
Copy link
Contributor

qoomon commented Aug 23, 2022

@realjenius your specific issue seems to be caused by a koltin reflection issue, see KotlinReflectionInternalError: Unresolved class" when inspecting anonymous Java class

@realjenius
Copy link

Thank you @qoomon ! I don't want to derail this issue then, but do you have suggestions for a reasonable workaround? This was working with Mockk 1.12.4, is some additional reflection logic causing this? I have a lot of developers that are using this test library in my company and I'm worried If I upgrade this a lot of teams might be impacted that weren't previously.

@qoomon
Copy link
Contributor

qoomon commented Aug 23, 2022

@realjenius oh I wasn't aware of the fact that is was working in version 1.12.4. Currently I have no working workaround :-(.

@qoomon
Copy link
Contributor

qoomon commented Aug 23, 2022

Probably we need to catch all exceptions Throwable within this method

} catch (_: UnsupportedOperationException) {

@qoomon
Copy link
Contributor

qoomon commented Aug 23, 2022

#890 should fix it

@vojkny
Copy link
Author

vojkny commented Aug 23, 2022

can you release it? 🙏

@stefanzilske
Copy link

This now also happens with 1.12.7 (cf. #884). It worked in 1.12.6, no changes other than upgrading to 1.12.7 and replacing io.mockk with io.mockk-jvm dependency (Maven).

Is there an easy workaround? If not can this fix be released soon? Otherwise we are stuck on 1.12.6.

@Raibaz
Copy link
Collaborator

Raibaz commented Aug 25, 2022

@stefanzilske can you please try downloading the master branch and deploying it to your local maven repository by doing ./gradlew publishToMavenLocal to check if #890 has fixed it?

@stefanzilske
Copy link

stefanzilske commented Aug 26, 2022

@Raibaz it was still failing with 1.12.8-SNAPSHOT, built from the master branch.

Then I noticed that I've got some mockk artifacts also in 1.12.4 on my classpath, because I am also using springmockk in 3.1.1. After excluding io.mockk:mockk from the springmockk dependency it works even with io.mockk:mockk-jvm:1.12.7.

So we need an updated version of springmockk, which is built upon mockk:1.12.7

@vojkny
Copy link
Author

vojkny commented Aug 26, 2022

So we need an updated version of springmockk, which is built upon mockk:1.12.7

That is not necessary, you can just tell gradle to exclude this dependency from springmockk.

@vojkny
Copy link
Author

vojkny commented Aug 26, 2022

Might be fixed by #872

🙏 for release

@stefanzilske
Copy link

stefanzilske commented Aug 26, 2022

So we need an updated version of springmockk, which is built upon mockk:1.12.7

That is not necessary, you can just tell gradle to exclude this dependency from springmockk.

Sure, but I am using mockk in 20 or so Maven multi module micro services, so I guess I have 40-60 places where I have to add this exclusion. Incrementing springmockk version along with mockk-jvm would be a lot easier 😉

I will add this as an issue at springmockk! Thanks a lot!

@vojkny
Copy link
Author

vojkny commented Sep 6, 2022

Might be fixed by #872

can we pls release it?

@Raibaz
Copy link
Collaborator

Raibaz commented Sep 15, 2022

Just released v1.12.8.

@Raibaz Raibaz closed this as completed Sep 15, 2022
@vojkny
Copy link
Author

vojkny commented Sep 15, 2022

I am sorry, but this is not resolved - demo build still fails on 1.12.8:

https://gitlab.com/knyttl/mockkdemo/-/jobs/3032515325

Downloading https://repo.maven.apache.org/maven2/io/mockk/mockk/1.12.8/mockk-1.12.8.pom to /builds/knyttl/mockkdemo/.gradle/.tmp/gradle_download10671493043139491605bin

And:

MockkDemo > testMockk() FAILED
    kotlin.reflect.jvm.internal.KotlinReflectionInternalError: Unresolved class: class org.elasticsearch.search.sort.SortOrder$1
        at kotlin.reflect.jvm.internal.KClassImpl.reportUnresolvedClass(KClassImpl.kt:328)
        at kotlin.reflect.jvm.internal.KClassImpl.access$reportUnresolvedClass(KClassImpl.kt:44)
        at kotlin.reflect.jvm.internal.KClassImpl$Data$descriptor$2.invoke(KClassImpl.kt:56)
        at kotlin.reflect.jvm.internal.KClassImpl$Data$descriptor$2.invoke(KClassImpl.kt:48)
        at kotlin.reflect.jvm.internal.ReflectProperties$LazySoftVal.invoke(ReflectProperties.java:93)
        at kotlin.reflect.jvm.internal.ReflectProperties$Val.getValue(ReflectProperties.java:32)
        at kotlin.reflect.jvm.internal.KClassImpl$Data.getDescriptor(KClassImpl.kt:48)
        at kotlin.reflect.jvm.internal.KClassImpl.getDescriptor(KClassImpl.kt:182)
        at kotlin.reflect.jvm.internal.KClassImpl.isValue(KClassImpl.kt:290)

@stefanzilske
Copy link

stefanzilske commented Sep 15, 2022

Yeah, still looks broken to me ... 1.12.8. jar is still empty, mockk-jvm is needed. So it's sill highly incompatible with older versions. And all that came with a patch level update 😔

/cc @aSemy

@aSemy
Copy link
Contributor

aSemy commented Sep 15, 2022

I am sorry, but this is not resolved - demo build still fails on 1.12.8:

https://gitlab.com/knyttl/mockkdemo/-/jobs/3032515325

Downloading https://repo.maven.apache.org/maven2/io/mockk/mockk/1.12.8/mockk-1.12.8.pom to /builds/knyttl/mockkdemo/.gradle/.tmp/gradle_download10671493043139491605bin

And:

MockkDemo > testMockk() FAILED
    kotlin.reflect.jvm.internal.KotlinReflectionInternalError: Unresolved class: class org.elasticsearch.search.sort.SortOrder$1
        at kotlin.reflect.jvm.internal.KClassImpl.reportUnresolvedClass(KClassImpl.kt:328)
        at kotlin.reflect.jvm.internal.KClassImpl.access$reportUnresolvedClass(KClassImpl.kt:44)
        at kotlin.reflect.jvm.internal.KClassImpl$Data$descriptor$2.invoke(KClassImpl.kt:56)
        at kotlin.reflect.jvm.internal.KClassImpl$Data$descriptor$2.invoke(KClassImpl.kt:48)
        at kotlin.reflect.jvm.internal.ReflectProperties$LazySoftVal.invoke(ReflectProperties.java:93)
        at kotlin.reflect.jvm.internal.ReflectProperties$Val.getValue(ReflectProperties.java:32)
        at kotlin.reflect.jvm.internal.KClassImpl$Data.getDescriptor(KClassImpl.kt:48)
        at kotlin.reflect.jvm.internal.KClassImpl.getDescriptor(KClassImpl.kt:182)
        at kotlin.reflect.jvm.internal.KClassImpl.isValue(KClassImpl.kt:290)

Thanks for the demo project. This is failing because it's missing an ElasticSearch class. If I change the test to remove it...

package tl.knyt

import io.mockk.every
import io.mockk.mockk
//import org.elasticsearch.search.sort.SortOrder
import org.junit.jupiter.api.Test

class MockkDemo {
    @Test
    fun testMockk() {
        val repo = mockk<TestClass>()
        every { repo.getSchedules() } returns "Foo"
    }
}

class TestClass {
//    fun getSchedules(sortOrder: SortOrder = SortOrder.ASC): String =
    fun getSchedules(sortOrder: String = "asd"): String =
        sortOrder.toString()
}

it works.

@aSemy
Copy link
Contributor

aSemy commented Sep 15, 2022

Yeah, still looks broken to me ... 1.12.8. jar is still empty, mockk-jvm is needed. So it's sill highly incompatible with older versions. And all that came with a patch level update 😔

@stefanzilske Can you make a new issue with a demo project, or link to open source one please? :) I'm particularly interested in the build config (pom.xml or build.gradle) - I suspect this is related to using Maven...

@vojkny
Copy link
Author

vojkny commented Sep 15, 2022

Thanks for the demo project. This is failing because it's missing an ElasticSearch class. If I change the test to remove it...

Of course this works if you use a simple class. My point is exactly that it does not work with this special case – this is the reason I had to use link the external project otherwise I couldn't reproduce it.

Also, as I mentioned, this worked correctly until 1.12.4.

@aSemy
Copy link
Contributor

aSemy commented Sep 15, 2022

Thanks for the demo project. This is failing because it's missing an ElasticSearch class. If I change the test to remove it...

Of course this works if you use a simple class. My point is exactly that it does not work with this special case – this is the reason I had to use link the external project otherwise I couldn't reproduce it.

Also, as I mentioned, this worked correctly until 1.12.4.

Okay, gotcha. I got confused by others in the thread mentioning the mockk-jvm issue, my bad!

I had another look and here's the full stacktrace (the io.mockk parts are most important)

 kotlin.reflect.jvm.internal.KotlinReflectionInternalError: Unresolved class: class org.elasticsearch.search.sort.SortOrder$1
        at kotlin.reflect.jvm.internal.KClassImpl.reportUnresolvedClass(KClassImpl.kt:328)
        at kotlin.reflect.jvm.internal.KClassImpl.access$reportUnresolvedClass(KClassImpl.kt:44)
        at kotlin.reflect.jvm.internal.KClassImpl$Data$descriptor$2.invoke(KClassImpl.kt:56)
        at kotlin.reflect.jvm.internal.KClassImpl$Data$descriptor$2.invoke(KClassImpl.kt:48)
        at kotlin.reflect.jvm.internal.ReflectProperties$LazySoftVal.invoke(ReflectProperties.java:93)
        at kotlin.reflect.jvm.internal.ReflectProperties$Val.getValue(ReflectProperties.java:32)
        at kotlin.reflect.jvm.internal.KClassImpl$Data.getDescriptor(KClassImpl.kt:48)
        at kotlin.reflect.jvm.internal.KClassImpl.getDescriptor(KClassImpl.kt:182)
        at kotlin.reflect.jvm.internal.KClassImpl.isValue(KClassImpl.kt:290)
        at io.mockk.core.ValueClassSupport.isValue_safe(ValueClassSupport.kt:63)
        at io.mockk.core.ValueClassSupport.getBoxedClass(ValueClassSupport.kt:32)
        at io.mockk.impl.InternalPlatform.packRef(InternalPlatform.kt:65)
        at io.mockk.impl.recording.ChainedCallDetector.detect$regularArgument(ChainedCallDetector.kt:49)
        at io.mockk.impl.recording.ChainedCallDetector.detect$detectArgMatchers(ChainedCallDetector.kt:114)
        at io.mockk.impl.recording.ChainedCallDetector.detect(ChainedCallDetector.kt:154)
        at io.mockk.impl.recording.SignatureMatcherDetector.detect(SignatureMatcherDetector.kt:93)
        at io.mockk.impl.recording.states.RecordingState.signMatchers(RecordingState.kt:39)
        at io.mockk.impl.recording.states.RecordingState.round(RecordingState.kt:31)
        at io.mockk.impl.recording.CommonCallRecorder.round(CommonCallRecorder.kt:50)
        at io.mockk.impl.eval.RecordedBlockEvaluator.record(RecordedBlockEvaluator.kt:63)
        at io.mockk.impl.eval.EveryBlockEvaluator.every(EveryBlockEvaluator.kt:30)
        at io.mockk.MockKDsl.internalEvery(API.kt:93)
        at io.mockk.MockKKt.every(MockK.kt:98)
        at tl.knyt.MockkDemo.testMockk(MockkDemo.kt:12)

So it looks like #890 wasn't enough. It also needs to catch KotlinReflectionInternalError. What do you think @qoomon?

@qoomon
Copy link
Contributor

qoomon commented Sep 15, 2022

@aSemy you are right. Because I don't know what kind of exceptions could be throw my initial solution was to catch all throwables.

@qoomon
Copy link
Contributor

qoomon commented Sep 15, 2022

@aSemy however we are already catching KotlinReflectionInternalError. It seems KotlinReflectionInternalError can't be catched.

@stefanzilske
Copy link

Yeah, still looks broken to me ... 1.12.8. jar is still empty, mockk-jvm is needed. So it's sill highly incompatible with older versions. And all that came with a patch level update 😔

@stefanzilske Can you make a new issue with a demo project, or link to open source one please? :) I'm particularly interested in the build config (pom.xml or build.gradle) - I suspect this is related to using Maven...

@aSemy #921 it is

@krissrex
Copy link

krissrex commented Sep 16, 2022

@aSemy however we are already catching KotlinReflectionInternalError.

Are you?

private val <T : Any> KClass<T>.isValue_safe: Boolean
get() = try {
this.isValue
} catch (_: UnsupportedOperationException) {
false
}

The isValue_safe exists multiple places, as seen here https://github.com/mockk/mockk/pull/890/files

@vojkny
Copy link
Author

vojkny commented Sep 19, 2022

so can we reopen this?

@qoomon
Copy link
Contributor

qoomon commented Sep 19, 2022

Should be fixed by #922. The extra catch somehow got lost during refactoring or reorganizing the project.

@vojkny
Copy link
Author

vojkny commented Sep 19, 2022

superb! can we release it then?

@chrispix
Copy link

Fixed in 1.13.1

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

Successfully merging a pull request may close this issue.