I want to use spyk for class with generic. It produces StackOverflowError. It is impossible to use every { childClazz.foobar(view) } just Runs and super.foobar(view) definitely need to be invoked
java.lang.StackOverflowError
at java.lang.Class.getDeclaredMethod(Class.java:2127)
at java.lang.Object.equals(Object.java:149)
at kotlin.jvm.internal.Intrinsics.areEqual(Intrinsics.java:164)
at kotlin.reflect.jvm.internal.KClassCacheKt.getOrCreateKotlinClass(kClassCache.kt:36)
at kotlin.reflect.jvm.internal.ReflectionFactoryImpl.getOrCreateKotlinClass(ReflectionFactoryImpl.java:45)
at kotlin.jvm.internal.Reflection.getOrCreateKotlinClass(Reflection.java:61)
at kotlin.jvm.JvmClassMappingKt.getKotlinClass(JvmClassMapping.kt:91)
at io.mockk.impl.instantiation.JvmMockFactoryHelper.toDescription(JvmMockFactoryHelper.kt:55)
at io.mockk.impl.instantiation.JvmMockFactoryHelper.access$toDescription(JvmMockFactoryHelper.kt:13)
at io.mockk.impl.instantiation.JvmMockFactoryHelper$mockHandler$1.invoke(JvmMockFactoryHelper.kt:17)
at io.mockk.impl.instantiation.JvmMockFactoryHelper$mockHandler$1.invoke(JvmMockFactoryHelper.kt:13)
at io.mockk.impl.instantiation.JvmMockFactoryKt$sam$MockKInvocationHandler$4dff1f07.invocation(JvmMockFactory.kt)
at io.mockk.proxy.MockKCallProxy.call(MockKCallProxy.java:24)
at com.app.ChildClazz.foobar(SimpleTest.kt:62)
at com.app.ChildClazz.foobar(SimpleTest.kt:55)
at sun.reflect.GeneratedMethodAccessor12.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
class SpyTest{
@Test
fun callFoobar(){
val view = mockk<SomeView>()
val childClazz = spyk(ChildClazz(), recordPrivateCalls = true)
childClazz.foobar(view)
assertk.assert(childClazz.called).isEqualTo(true)
}
}
private interface ParentView
private interface SomeView : ParentView
private interface ParentInterface<V : ParentView> {
fun foobar(view: V)
}
private abstract class ParentClazz<V : ParentView> : ParentInterface<V> {
override fun foobar(view: V) {
}
}
private class ChildClazz : ParentClazz<SomeView>() {
var called: Boolean = false
override fun foobar(view: SomeView) {
super.foobar(view)
called = true
}
}
Issue is bridge method handling:
// access flags 0x1
public foobar(Labc/Sub;)V
@Lorg/jetbrains/annotations/NotNull;() // invisible, parameter 0
L0
ALOAD 1
LDC "view"
INVOKESTATIC kotlin/jvm/internal/Intrinsics.checkParameterIsNotNull (Ljava/lang/Object;Ljava/lang/String;)V
L1
LINENUMBER 29 L1
ALOAD 0
ALOAD 1
CHECKCAST abc/Base
INVOKESPECIAL abc/ParentClazz.foobar (Labc/Base;)V
L2
LINENUMBER 30 L2
ALOAD 0
ICONST_1
PUTFIELD abc/ChildClazz.called : Z
L3
LINENUMBER 31 L3
RETURN
L4
LOCALVARIABLE this Labc/ChildClazz; L0 L4 0
LOCALVARIABLE view Labc/Sub; L0 L4 1
MAXSTACK = 2
MAXLOCALS = 2
// access flags 0x1041
public synthetic bridge foobar(Labc/Base;)V
L0
LINENUMBER 25 L0
ALOAD 0
ALOAD 1
CHECKCAST abc/Sub
INVOKEVIRTUAL abc/ChildClazz.foobar (Labc/Sub;)V
RETURN
MAXSTACK = 2
MAXLOCALS = 2
Need some time to analyze and fix it.
I have an approach to resolve it. But it requires quite serious changes as seems byte buddy doesn't support calling "super" methods. Checking that here: https://github.com/raphw/byte-buddy/issues/483
Hi there, any news about this bug?
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions. If you are sure that this issue is important and should not be marked as stale just ask to put an important label.
This is definitely a blocking one for me
Any updates for now?