mockk: java.lang.IncompatibleClassChangeError: Superclass my.project.TestInterface of my.project.TestInterface_1_Proxy is an interface (declaration of 'my.project.TestInterface_1_Proxy' appears in /data/user/0/my.project.test/app_dxmaker_cache/Generated_712335553.jar)
Prerequisites
- I am running the latest version
- I checked the documentation and found no answer
- I checked to make sure that this issue has not already been filed
Expected Behavior
I expect my android instrumentation tests to be running as they were on 1.13.3 (now failing on 1.13.4 with the exception described below)
Current Behavior
When running an Android instrumented test that uses mockk and initializes dependencies with koin I get test failure with a stacktrace mentioned below
This happens with a very simple setup of trying to inject a class into a viewModel that I want to mock using mockk. When Iβm not trying to inject a class into the viewModel the test passes green.
Steps to Reproduce
- With the setup mentioned below, run the androidTest and it will fail with the below mentioned stacktrace
java.lang.IncompatibleClassChangeError: Superclass my.project.TestInterface of my.project.TestInterface_1_Proxy is an interface (declaration of 'my.project.TestInterface_1_Proxy' appears in /data/user/0/de.my.project.test/app_dxmaker_cache/Generated_712335553.jar)
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.13.4 (wasnβt happening on 1.13.3)
- OS: Android API33
- Kotlin version: 1.8.0
- JDK version: 11.0.13
- JUnit version: 4.13.2
- Type of test: android instrumented test
Stack trace
java.lang.IncompatibleClassChangeError: Superclass my.project.TestInterface of my.project.TestInterface_1_Proxy is an interface (declaration of 'my.project.TestInterface_1_Proxy' appears in /data/user/0/de.my.project.test/app_dxmaker_cache/Generated_712335553.jar)
at java.lang.VMClassLoader.findLoadedClass(Native Method)
at java.lang.ClassLoader.findLoadedClass(ClassLoader.java:738)
at java.lang.ClassLoader.loadClass(ClassLoader.java:363)
at java.lang.ClassLoader.loadClass(ClassLoader.java:312)
at com.android.dx.stock.ProxyBuilder.loadClass(ProxyBuilder.java:358)
at com.android.dx.stock.ProxyBuilder.buildProxyClass(ProxyBuilder.java:340)
at io.mockk.proxy.android.transformation.AndroidSubclassInstrumentation.subclass(AndroidSubclassInstrumentation.kt:37)
at io.mockk.proxy.common.ProxyMaker.subclass(ProxyMaker.kt:148)
at io.mockk.proxy.common.ProxyMaker.proxy(ProxyMaker.kt:54)
at io.mockk.impl.instantiation.JvmMockFactory.newProxy(JvmMockFactory.kt:34)
at io.mockk.impl.instantiation.AbstractMockFactory.newProxy$default(AbstractMockFactory.kt:24)
at io.mockk.impl.instantiation.AbstractMockFactory.mockk(AbstractMockFactory.kt:59)
at my.project.TestTest$koinTestRule$1$1$1.invoke(TestTest.kt:58)
at my.project.TestTest$koinTestRule$1$1$1.invoke(TestTest.kt:28)
... [the stacktrace continues but doesn't seem to relevant after this point]
Minimal reproducible code (the gist of this issue)
The relevant classes (simplified) below outline the setup in which this is reproducible
koin versions:
val koinCoreVersion = "3.3.2"
api("io.insert-koin:koin-core:$koinCoreVersion")
api("io.insert-koin:koin-test:$koinCoreVersion")
api("io.insert-koin:koin-test-junit4:$koinCoreVersion")
api("io.insert-koin:koin-test-junit5:$koinCoreVersion")
val koinAndroidVersion = "3.3.2"
api("io.insert-koin:koin-android:$koinAndroidVersion")
api("io.insert-koin:koin-androidx-navigation:$koinAndroidVersion")
api("io.insert-koin:koin-androidx-compose:3.4.1")
Test class:
class TestTest : KoinTest {
@get:Rule(order = 1)
val koinTestRule = KoinTestRule.create {
modules(
module {
single<TestInterface> { mockk(relaxed = true) }
},
testModule
)
}
@get:Rule(order = 2)
val composeTestRule = createAndroidIntentComposeRule<TestActivity> {
Intent(it, TestActivity::class.java)
}
@Test
fun test_test() {
composeTestRule.onNodeWithTag("test_tag").assertExists()
}
}
The Activity:
class TestActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
val viewModel: TestViewModel = getViewModel()
Text(text = "text", modifier = Modifier.testTag("test_tag"))
}
}
}
ViewModel:
class TestViewModel(testInterface: TestInterface) : ViewModel()
The interface I want to inject:
interface TestInterface
The koin module:
val testModule = module {
viewModel {
TestViewModel(get())
}
}
About this issue
- Original URL
- State: closed
- Created a year ago
- Reactions: 126
- Comments: 25 (5 by maintainers)
Commits related to this issue
- Downgrade Mockk version due to a bug https://github.com/mockk/mockk/issues/1035 — committed to GisoBartels/kaster by GisoBartels a year ago
- Downgrade Mockk version due to a bug https://github.com/mockk/mockk/issues/1035 — committed to GisoBartels/kaster by GisoBartels a year ago
- Bug 1834746 - Replace OAuthAccount mock with implementation mock. See also mockk bug: https://github.com/mockk/mockk/issues/1035. — committed to mcarare/firefox-android by mcarare a year ago
- Bug 1834746 - Replace OAuthAccount mock with implementation mock. See also mockk bug: https://github.com/mockk/mockk/issues/1035. — committed to mcarare/firefox-android by mcarare a year ago
- Bug 1834746 - Replace OAuthAccount mock with implementation mock. See also mockk bug: https://github.com/mockk/mockk/issues/1035. — committed to mozilla-mobile/firefox-android by mcarare a year ago
- Revert mockk to 1.13.3 Reverting due to the same issues reported in: https://github.com/mockk/mockk/issues/1035 — committed to mullvad/mullvadvpn-app by albin-mullvad a year ago
- Bug 1834746 - Replace OAuthAccount mock with implementation mock. See also mockk bug: https://github.com/mockk/mockk/issues/1035. — committed to fork-maintainers/iceraven-browser by mcarare a year ago
- Fix #1035 This is a bug caused by d9ceddcbdd1d7f6e6cad291bb1a3d7bdb512ab68 — committed to kubode/mockk by kubode a year ago
- Fix #1035 This is a bug caused by d9ceddcbdd1d7f6e6cad291bb1a3d7bdb512ab68 — committed to kubode/mockk by kubode a year ago
- Merge pull request #1145 from LeonRa/master Fix `IncompatibleClassChangeError` in Android instrumentation test (#1035) — committed to mockk/mockk by Raibaz 10 months ago
Folks, please react with a π on the initial comment instead of leaving new a comment to confirm, each comment means an email to all the issue participants π¬
I still have this on the latest 1.13.5, it only affects instrumented tests, unit tests seems to deal ok with it
Same here while running android instrumentation tests (UI tests). Older versions works fine. Fatal Exception: java.lang.IncompatibleClassChangeError Superclass kotlinx.coroutines.flow.StateFlow of kotlinx.coroutines.flow.StateFlow_1_Proxy is an interface (declaration of βkotlinx.coroutines.flow.StateFlow_1_Proxyβ appears in /data/user/0/package/app_dxmaker_cache/Generated_-767958641.jar)
Just another confirmation, seeing this on 1.13.5 & 1.13.4, so weβre forced to downgrade back to 1.13.3
I still encountered this problem on 1.13.4
Just reporting that the issue is still present in version 1.13.7
Unfortunately I can confirm that mocking at instrumented is immposible.
java.lang.IncompatibleClassChangeError: Superclass kotlinx.coroutines.flow.Flow of kotlinx.coroutines.flow.Flow_1_Proxy is an interface (declaration of 'kotlinx.coroutines.flow.Flow_1_Proxy'
Just adding onto the confirmation pile⦠seeing the same issue on 1.13.5 after moving from 1.13.2.
Good callout @oliverspryn! I locally did the following locally and the unit tests appear to pass again:
ProxyMaker
. However, I donβt think that the two were identical, given that the Android-modified version of the class tends to differ somewhat from that of later JDKs the JVM unit tests run against.Iβd love to locally publish a version of mockk to test against a real Android project to further validate the fix, but unfortunately couldnβt find instructions to do so. I tried running
gradle publish
which is supposed to use mavenLocal, but unfortunately that appears to fail locally with the following, likely due to my environment being different:Happy to put up a fix once I can validate the behavior. Help getting things running would be greatly appreciated π
I could be wrong, but Iβm wondering if #1025 is responsible for this break since people report
1.13.3
didnβt have this issue and1.13.4
does, based on this changelog.Same issue here. Trying to mock a function that takes a List using any(). Downgrade to 1.13.2 works.
If anyone is trying to find a workaround for this in the mean time, I was able to resolve this issue by downgrading to v1.13.2
Seems to be fixed with version
1.13.8
@LeonRa running the
gradle publish
command from the main branch is working fine (as documented in CONTRIBUTING.md). Are you sure you donβt override Gradle version? (try runninggradlew publish
command instead) Also, check if you are running a supported Java version.gradlew build
outputIβve figured out the cause of this problem and tried to fix it in #1129, but Iβve run into other problems with the existing Android Instrumentation Test failing. Iβm not familiar with technology such as Proxy, so I need someoneβs help.
Same here, currently migrating an Android projetct Kotlin to full compose Seem to be the swith to junit5, still many libs using junit4 in test utils lib like
androidTestImplementation(βandroidx.compose.ui:ui-test-junit4:$composeVersionβ)
=> just changing this line mockkVersion=1.13.3 (1.13.4 and 1.13.5 do not work)
Full project using mockk available here => https://github.com/boitakub/Bogadex/tree/feature/compose
Having encountred this one in 1.13.3 version : https://github.com/mockk/mockk/issues/702