8000 Version 1.14.0 introduces `class redefinition failed: invalid class` in Android local tests · Issue #1375 · mockk/mockk · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Version 1.14.0 introduces class redefinition failed: invalid class in Android local tests #1375

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

Closed
bddckr opened this issue Apr 10, 2025 · 12 comments

Comments

@bddckr
Copy link
bddckr commented Apr 10, 2025

On MockK version 1.13.17, this code in the test folder of an Android library project works:

package mypackage

import android.net.Uri
import io.mockk.every
import io.mockk.mockk
import io.mockk.mockkStatic
import io.mockk.unmockkStatic
import org.junit.jupiter.api.Test

class Test {
    @Test
    fun test() {
        try {
            mockkStatic(Uri::class)
            every { Uri.parse(any()) } answers { mockk() }
        } finally {
            unmockkStatic(Uri::class)
        }
    }
}

But in MockK 1.14.0 it fails:

class redefinition failed: invalid class
java.lang.InternalError: class redefinition failed: invalid class
	at java.instrument/sun.instrument.InstrumentationImpl.retransformClasses0(Native Method)
	at java.instrument/sun.instrument.InstrumentationImpl.retransformClasses(Unknown Source)
	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.JvmStaticMockFactory$staticMockk$3.invoke(JvmStaticMockFactory.kt:45)
	at io.mockk.impl.instantiation.JvmStaticMockFactory$staticMockk$3.invoke(JvmStaticMockFactory.kt:45)
	at io.mockk.impl.stub.MockKStub.dispose(MockKStub.kt:321)
	at io.mockk.impl.instantiation.JvmStaticMockFactory$staticMockk$4.invoke(JvmStaticMockFactory.kt:55)
	at io.mockk.impl.instantiation.JvmStaticMockFactory$staticMockk$4.invoke(JvmStaticMockFactory.kt:50)
	at io.mockk.MockKCancellationRegistry$RegistryPerType.cancel(API.kt:2530)
	at mypackage.Test.test(Test.kt:80)
	at java.base/java.lang.reflect.Method.invoke(Unknown Source)
	at java.base/java.util.ArrayList.forEach(Unknown Source)
	at java.base/java.util.ArrayList.forEach(Unknown Source)

Versions used:

  • MockK: 1.14.0
  • Android Gradle Plugin: 8.9.1
  • Kotlin: 2.1.20

I've also tried depending on net.bytebuddy:byte-buddy and net.bytebuddy:byte-buddy-agent in this project to change the resolved version that's used. I then set it to the latest available Byte Buddy version - 1.17.5. This didn't change anything - it's still failing the same way.

@Raibaz
Copy link
Collaborator
Raibaz commented Apr 10, 2025

@sgerke-1L @marcelstoer this looks related to the switch from redefine to decorate

@marcelstoer
Copy link
Contributor

@bddckr can you please see #1118 (comment) for a way of finding out what exactly the JVM has issues with.

@bddckr
Copy link
Author
bddckr commented Apr 10, 2025

While trying to do that to provide more info, I've had to restart Android Studio. Once restarted, I could no longer reproduce 🤔 I've definitely synced the project in the IDE when I did my changes, and confirmed that the attempt to use newer Byte Buddy versions also applied before restarting.

Sorry for wasting your time, closing this!

@bddckr bddckr closed this as completed Apr 10, 2025
@sgerke-1L
Copy link
Contributor

No worries, please report back if the issue re-occurs!

@marcelstoer
Copy link
Contributor

@Raibaz Just like with #1373... issue cannot be reproduced. Is there something unique about 1.14 maybe or have you seen this with other updates before?

@bddckr
Copy link
Author
bddckr commented Apr 10, 2025

Just as I get this pushed to my CI pipeline, it fails again.

That helped me find the reason why I wasn't able to reproduce anymore: It only reproduces if I run the test with code coverage enabled!

Not via Android Studio/IntelliJ's Run With Coverage button, but instead by telling AGP to turn on coverage for local tests:

android {
    buildTypes {
        debug { 
            enableUnitTestCoverage = true
        }
    }
}

So perhaps this is an issue only when JaCoCo is applied?

As a test, I've set android.testCoverage.jacocoVersion to the latest version 0.8.13 instead of relying on the default AGP sets - no change. The same class redefinition failed: invalid class keeps happening.

Thanks a lot for handling these issues, btw - much appreciated!

@bddckr bddckr reopened this Apr 10, 2025
@bddckr
Copy link
Author
bddckr commented Apr 10, 2025

Got the additional info via

tasks.withType<Test>().configureEach {
    jvmArgs("-Xlog:redefine+class*=trace:stdout")
}
Details
[0.686s][trace][redefine,class,iklass,purge] Class unloading: should_clean_previous_versions = false
[0.826s][debug][redefine,class,load        ] loading name=android.net.Uri kind=101 (avail_mem=135936K)
[0.949s][trace][redefine,class,normalize   ] Method matched: new: android.net.Uri.getScheme()Ljava/lang/String; [0] == old: android.net.Uri.getScheme()Ljava/lang/String; [0]
[0.949s][trace][redefine,class,normalize   ] Method matched: new: android.net.Uri.isOpaque()Z [1] == old: android.net.Uri.isOpaque()Z [1]
[0.949s][trace][redefine,class,normalize   ] Method matched: new: android.net.Uri.getHost()Ljava/lang/String; [2] == old: android.net.Uri.getHost()Ljava/lang/String; [2]
[0.949s][trace][redefine,class,normalize   ] Method matched: new: android.net.Uri.getPort()I [3] == old: android.net.Uri.getPort()I [3]
[0.949s][trace][redefine,class,normalize   ] Method matched: new: android.net.Uri.getAuthority()Ljava/lang/String; [4] == old: android.net.Uri.getAuthority()Ljava/lang/String; [4]
[0.949s][trace][redefine,class,normalize   ] Method matched: new: android.net.Uri.isRelative()Z [5] == old: android.net.Uri.isRelative()Z [5]
[0.949s][trace][redefine,class,normalize   ] Method matched: new: android.net.Uri.getQuery()Ljava/lang/String; [6] == old: android.net.Uri.getQuery()Ljava/lang/String; [6]
[0.949s][trace][redefine,class,normalize   ] Method matched: new: android.net.Uri.getPath()Ljava/lang/String; [7] == old: android.net.Uri.getPath()Ljava/lang/String; [7]
[0.949s][trace][redefine,class,normalize   ] Method matched: new: android.net.Uri.getUserInfo()Ljava/lang/String; [8] == old: android.net.Uri.getUserInfo()Ljava/lang/String; [8]
[0.949s][trace][redefine,class,normalize   ] Method matched: new: android.net.Uri.getSchemeSpecificPart()Ljava/lang/String; [9] == old: android.net.Uri.getSchemeSpecificPart()Ljava/lang/String; [9]
[0.949s][trace][redefine,class,normalize   ] Method matched: new: android.net.Uri.getFragment()Ljava/lang/String; [10] == old: android.net.Uri.getFragment()Ljava/lang/String; [10]
[0.949s][trace][redefine,class,normalize   ] Method matched: new: android.net.Uri.<init>()V [11] == old: android.net.Uri.<init>()V [11]
[0.949s][trace][redefine,class,normalize   ] Method matched: new: android.net.Uri.<clinit>()V [12] == old: android.net.Uri.<clinit>()V [12]
[0.949s][trace][redefine,class,normalize   ] Method matched: new: android.net.Uri.equals(Ljava/lang/Object;)Z [13] == old: android.net.Uri.equals(Ljava/lang/Object;)Z [13]
[0.949s][trace][redefine,class,normalize   ] Method matched: new: android.net.Uri.toString()Ljava/lang/String; [14] == old: android.net.Uri.toString()Ljava/lang/String; [14]
[0.949s][trace][redefine,class,normalize   ] Method matched: new: android.net.Uri.hashCode()I [15] == old: android.net.Uri.hashCode()I [15]
[0.949s][trace][redefine,class,normalize   ] Method matched: new: android.net.Uri.compareTo(Landroid/net/Uri;)I [16] == old: android.net.Uri.compareTo(Landroid/net/Uri;)I [16]
[0.949s][trace][redefine,class,normalize   ] Method matched: new: android.net.Uri.compareTo(Ljava/lang/Object;)I [17] == old: android.net.Uri.compareTo(Ljava/lang/Object;)I [17]
[0.949s][trace][redefine,class,normalize   ] Method matched: new: android.net.Uri.decode(Ljava/lang/String;)Ljava/lang/String; [18] == old: android.net.Uri.decode(Ljava/lang/String;)Ljava/lang/String; [18]
[0.949s][trace][redefine,class,normalize   ] Method matched: new: android.net.Uri.encode(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String; [19] == old: android.net.Uri.encode(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String; [19]
[0.949s][trace][redefine,class,normalize   ] Method matched: new: android.net.Uri.encode(Ljava/lang/String;)Ljava/lang/String; [20] == old: android.net.Uri.encode(Ljava/lang/String;)Ljava/lang/String; [20]
[0.949s][trace][redefine,class,normalize   ] Method matched: new: android.net.Uri.isAbsolute()Z [21] == old: android.net.Uri.isAbsolute()Z [21]
[0.949s][trace][redefine,class,normalize   ] Method matched: new: android.net.Uri.parse(Ljava/lang/String;)Landroid/net/Uri; [22] == old: android.net.Uri.parse(Ljava/lang/String;)Landroid/net/Uri; [22]
[0.949s][trace][redefine,class,normalize   ] Method matched: new: android.net.Uri.getEncodedSchemeSpecificPart()Ljava/lang/String; [23] == old: android.net.Uri.getEncodedSchemeSpecificPart()Ljava/lang/String; [23]
[0.949s][trace][redefine,class,normalize   ] Method matched: new: android.net.Uri.getBooleanQueryParameter(Ljava/lang/String;Z)Z [24] == old: android.net.Uri.getBooleanQueryParameter(Ljava/lang/String;Z)Z [24]
[0.949s][trace][redefine,class,normalize   ] Method matched: new: android.net.Uri.getEncodedAuthority()Ljava/lang/String; [25] == old: android.net.Uri.getEncodedAuthority()Ljava/lang/String; [25]
[0.949s][trace][redefine,class,normalize   ] Method matched: new: android.net.Uri.getEncodedUserInfo()Ljava/lang/String; [26] == old: android.net.Uri.getEncodedUserInfo()Ljava/lang/String; [26]
[0.949s][trace][redefine,class,normalize   ] Method matched: new: android.net.Uri.getEncodedQuery()Ljava/lang/String; [27] == old: android.net.Uri.getEncodedQuery()Ljava/lang/String; [27]
[0.949s][trace][redefine,class,normalize   ] Method matched: new: android.net.Uri.getEncodedFragment()Ljava/lang/String; [28] == old: android.net.Uri.getEncodedFragment()Ljava/lang/String; [28]
[0.949s][trace][redefine,class,normalize   ] Method matched: new: android.net.Uri.getPathSegments()Ljava/util/List; [29] == old: android.net.Uri.getPathSegments()Ljava/util/List; [29]
[0.949s][trace][redefine,class,normalize   ] Method matched: new: android.net.Uri.getLastPathSegment()Ljava/lang/String; [30] == old: android.net.Uri.getLastPathSegment()Ljava/lang/String; [30]
[0.949s][trace][redefine,class,normalize   ] Method matched: new: android.net.Uri.getQueryParameterNames()Ljava/util/Set; [31] == old: android.net.Uri.getQueryParameterNames()Ljava/util/Set; [31]
[0.949s][trace][redefine,class,normalize   ] Method matched: new: android.net.Uri.getQueryParameters(Ljava/lang/String;)Ljava/util/List; [32] == old: android.net.Uri.getQueryParameters(Ljava/lang/String;)Ljava/util/List; [32]
[0.949s][trace][redefine,class,normalize   ] Method matched: new: android.net.Uri.getQueryParameter(Ljava/lang/String;)Ljava/lang/String; [33] == old: android.net.Uri.getQueryParameter(Ljava/lang/String;)Ljava/lang/String; [33]
[0.949s][trace][redefine,class,normalize   ] Method matched: new: android.net.Uri.normalizeScheme()Landroid/net/Uri; [34] == old: android.net.Uri.normalizeScheme()Landroid/net/Uri; [34]
[0.949s][trace][redefine,class,normalize   ] Method matched: new: android.net.Uri.withAppendedPath(Landroid/net/Uri;Ljava/lang/String;)Landroid/net/Uri; [35] == old: android.net.Uri.withAppendedPath(Landroid/net/Uri;Ljava/lang/String;)Landroid/net/Uri; [35]
[0.949s][trace][redefine,class,normalize   ] Method matched: new: android.net.Uri.$jacocoInit()[Z [36] == old: android.net.Uri.$jacocoInit()[Z [36]
[0.949s][trace][redefine,class,normalize   ] Method matched: new: android.net.Uri.isHierarchical()Z [37] == old: android.net.Uri.isHierarchical()Z [37]
[0.949s][trace][redefine,class,normalize   ] Method matched: new: android.net.Uri.getEncodedPath()Ljava/lang/String; [38] == old: android.net.Uri.getEncodedPath()Ljava/lang/String; [38]
[0.949s][trace][redefine,class,normalize   ] Method matched: new: android.net.Uri.buildUpon()Landroid/net/Uri$Builder; [39] == old: android.net.Uri.buildUpon()Landroid/net/Uri$Builder; [39]
[0.949s][trace][redefine,class,normalize   ] Method matched: new: android.net.Uri.fromFile(Ljava/io/File;)Landroid/net/Uri; [40] == old: android.net.Uri.fromFile(Ljava/io/File;)Landroid/net/Uri; [40]
[0.949s][trace][redefine,class,normalize   ] Method matched: new: android.net.Uri.fromParts(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Landroid/net/Uri; [41] == old: android.net.Uri.fromParts(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Landroid/net/Uri; [41]
[0.949s][trace][redefine,class,normalize   ] Method matched: new: android.net.Uri.writeToParcel(Landroid/os/Parcel;Landroid/net/Uri;)V [42] == old: android.net.Uri.writeToParcel(Landroid/os/Parcel;Landroid/net/Uri;)V [42]
[0.949s][info ][redefine,class,constantpool] old_cp_len=189, scratch_cp_len=236
[0.949s][debug][redefine,class,constantpool] after pass 0: merge_cp_len=189
[0.949s][debug][redefine,class,constantpool] after pass 1a: merge_cp_len=189, scratch_i=189, index_map_len=0
[0.949s][debug][redefine,class,constantpool] after pass 1b: merge_cp_len=236, scratch_i=236, index_map_len=0
[0.949s][info ][redefine,class,constantpool] merge_cp_len=236, index_map_len=0
[0.949s][debug][redefine,class,load        ] loaded name=android.net.Uri (avail_mem=135936K)
[0.951s][trace][redefine,class,obsolete,mark] mark decode((Ljava/lang/String;)Ljava/lang/String;) as obsolete
[0.951s][trace][redefine,class,obsolete,mark] mark encode((Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;) as obsolete
[0.951s][trace][redefine,class,obsolete,mark] mark encode((Ljava/lang/String;)Ljava/lang/String;) as obsolete
[0.951s][trace]
8000
[redefine,class,obsolete,mark] mark parse((Ljava/lang/String;)Landroid/net/Uri;) as obsolete
[0.951s][trace][redefine,class,obsolete,mark] mark withAppendedPath((Landroid/net/Uri;Ljava/lang/String;)Landroid/net/Uri;) as obsolete
[0.951s][trace][redefine,class,obsolete,mark] mark $jacocoInit(()[Z) as obsolete
[0.951s][trace][redefine,class,obsolete,mark] mark fromFile((Ljava/io/File;)Landroid/net/Uri;) as obsolete
[0.951s][trace][redefine,class,obsolete,mark] mark fromParts((Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Landroid/net/Uri;) as obsolete
[0.951s][trace][redefine,class,obsolete,mark] mark writeToParcel((Landroid/os/Parcel;Landroid/net/Uri;)V) as obsolete
[0.951s][trace][redefine,class,obsolete,mark] EMCP_cnt=34, obsolete_cnt=9
[0.951s][trace][redefine,class,iklass,add   ] adding previous version ref for android.net.Uri, EMCP_cnt=34
[0.951s][trace][redefine,class,iklass,add   ] scratch class not added; no methods are running
[0.951s][info ][redefine,class,load         ] redefined name=android.net.Uri, count=1 (avail_mem=135936K)
[0.952s][debug][redefine,class,nmethod      ] Marked dependent nmethods for deopt
[0.955s][trace][redefine,class,obsolete,metadata] calling check_class
[0.956s][info ][redefine,class,timer            ] vm_op: all=129  prologue=123  doit=6
[0.956s][info ][redefine,class,timer            ] redefine_single_class: phase1=0  phase2=0
[1.341s][trace][redefine,class,iklass,purge     ] Class unloading: should_clean_previous_versions = false

@sgerke-1L
Copy link
Contributor

It looks like jacoco is doing also instrumentation to track code coverage, which now interferes with mockk's instrumentation.

@nico-arianto
Copy link
nico-arianto commented Apr 10, 2025

It's happen to me also with this code:

    @BeforeEach
    fun beforeEach() {
        mockkStatic(RandomStringUtils::class)
    }

    @AfterEach
    fun afterEach() {
        unmockkStatic(RandomStringUtils::class)
    }

    @Test
    fun `should ...`() {
        every { RandomStringUtils.secure().nextAlphanumeric(any()) } returns REFERRAL_CODE
        ...
        verify(exactly = 1) { RandomStringUtils.secure().nextAlphanumeric(8) }
    }

Error:

java.lang.ExceptionInInitializerError
	at 
	at io.mockk.impl.eval.RecordedBlockEvaluator$record$block$1.invoke(RecordedBlockEvaluator.kt:24)
	at io.mockk.impl.eval.RecordedBlockEvaluator$enhanceWithRethrow$1.invoke(RecordedBlockEvaluator.kt:76)
	at io.mockk.impl.recording.JvmAutoHinter.autoHint(JvmAutoHinter.kt:23)
	at io.mockk.impl.eval.RecordedBlockEvaluator.record(RecordedBlockEvaluator.kt:39)
	at io.mockk.impl.eval.EveryBlockEvaluator.every(EveryBlockEvaluator.kt:30)
	at io.mockk.MockKDsl.internalEvery(API.kt:94)
	at io.mockk.MockKKt.every(MockK.kt:148)
	at java.base/java.lang.reflect.Method.invoke(Method.java:580)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)
	Suppressed: java.lang.InternalError: class redefinition failed: invalid class
		at java.instrument/sun.instrument.InstrumentationImpl.retransformClasses0(Native Method)
		at java.instrument/sun.instrument.InstrumentationImpl.retransformClasses(InstrumentationImpl.java:225)
		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.JvmStaticMockFactory$staticMockk$3.invoke(JvmStaticMockFactory.kt:45)
		at io.mockk.impl.instantiation.JvmStaticMockFactory$staticMockk$3.invoke(JvmStaticMockFactory.kt:45)
		at io.mockk.impl.stub.MockKStub.dispose(MockKStub.kt:321)
		at io.mockk.impl.instantiation.JvmStaticMockFactory$staticMockk$4.invoke(JvmStaticMockFactory.kt:55)
		at io.mockk.impl.instantiation.JvmStaticMockFactory$staticMockk$4.invoke(JvmStaticMockFactory.kt:50)
		at io.mockk.MockKCancellationRegistry$RegistryPerType.cancel(API.kt:2530)
		... 3 more
Caused by: java.lang.ArrayIndexOutOfBoundsException: Index 124 out of bounds for length 0
	at org.apache.commons.lang3.RandomStringUtils.<clinit>(RandomStringUtils.java:83)
	... 12 more

Where previously it's fine with 1.13.17, but it's failed with 1.14.0

Info
Kotlin: 2.1.20
JVM: openjdk 21.0.6 2025-01-21 LTS
JaCoCo Tool Version: 0.8.13

@laurentvoodoo
Copy link

Same issue here on

    companion object {
        @BeforeAll
        @JvmStatic
        internal fun init() {
            mockkStatic(Environment::class)
            every { Environment.getExternalStoragePublicDirectory(any()) } answers { File("/sdcard/downloads") }
        }
    }
java.lang.ExceptionInInitializerError
	at app.myapp.core.data.VersionRepositoryTest$Companion.init$lambda$0(VersionRepositoryTest.kt:499)
	at io.mockk.impl.eval.RecordedBlockEvaluator$record$block$1.invoke(RecordedBlockEvaluator.kt:24)
	at io.mockk.impl.eval.RecordedBlockEvaluator$enhanceWithRethrow$1.invoke(RecordedBlockEvaluator.kt:76)
	at io.mockk.impl.recording.JvmAutoHinter.autoHint(JvmAutoHinter.kt:23)
	at io.mockk.impl.eval.RecordedBlockEvaluator.record(RecordedBlockEvaluator.kt:39)
	at io.mockk.impl.eval.EveryBlockEvaluator.every(EveryBlockEvaluator.kt:30)
	at io.mockk.MockKDsl.internalEvery(API.kt:94)
	at io.mockk.MockKKt.every(MockK.kt:148)
	at app.myapp.core.data.VersionRepositoryTest$Companion.init$data_debugUnitTest(VersionRepositoryTest.kt:499)
	at app.myapp.core.data.VersionRepositoryTest.init$data_debugUnitTest(VersionRepositoryTest.kt)
	at java.base/java.lang.reflect.Method.invoke(Unknown Source)
	at java.base/java.util.ArrayList.forEach(Unknown Source)
Caused by: java.lang.ArrayIndexOutOfBoundsException: Index 18 out of bounds for length 0
	at android.os.Environment.<clinit>(Environment.java)
	... 12 more

@sgerke-1L
Copy link
Contributor

Thanks for providing the helpful examples and debug output. Based on the examples, I was able to extract a reproducer test-case and a proposed fix.

There seems to be an issue with decorate when it is used for static intercepts. I don't fully understand the issue, especially because it only seems to manifest in conjunction with jacoco, but I suspect it has to do with how static class members are initialized.

I've put up #1376 as one way to fix it. There is another mentioned in the PR comment. I'd appreciate feedback on what to use.

Raibaz added a commit that referenced this issue Apr 28, 2025
Use redefine if mockkStatic is used (fix candidate for #1375)
@bddckr
Copy link
Author
bddckr commented Apr 30, 2025

I can confirm that this is fixed by 1.14.2. Thanks a lot!

@bddckr bddckr closed this as completed Apr 30, 2025
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

6 participants
0