From ce37b26705a2e9b5ffd5e01fe8d1a0c3c05a13d0 Mon Sep 17 00:00:00 2001 From: Daniil Iastremskii Date: Thu, 29 Sep 2022 17:55:10 +0300 Subject: [PATCH 1/3] Add tests for issue #934 --- .../kotlin/io/mockk/it/SealedClassTest.kt | 22 +++++++++++++++++++ .../kotlin/io/mockk/it/SealedInterfaceTest.kt | 22 +++++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/modules/mockk/src/commonTest/kotlin/io/mockk/it/SealedClassTest.kt b/modules/mockk/src/commonTest/kotlin/io/mockk/it/SealedClassTest.kt index efa39cab2..072ce1346 100644 --- a/modules/mockk/src/commonTest/kotlin/io/mockk/it/SealedClassTest.kt +++ b/modules/mockk/src/commonTest/kotlin/io/mockk/it/SealedClassTest.kt @@ -2,6 +2,8 @@ package io.mockk.it import io.mockk.every import io.mockk.mockk +import org.junit.jupiter.api.condition.DisabledForJreRange +import org.junit.jupiter.api.condition.JRE import kotlin.test.Test import kotlin.test.assertEquals @@ -30,6 +32,22 @@ class SealedClassTest { assertEquals(Leaf(1), result) } + @Test + @DisabledForJreRange( + min = JRE.JAVA_17, + disabledReason = "https://github.com/mockk/mockk/issues/934" + ) + fun serviceTakesSealedClassAsInput() { + val formattedNode = "Formatted node" + val factory = mockk { + every { format(any()) } answers { formattedNode } + } + + val result = factory.format(Root(0)) + + assertEquals(formattedNode, result) + } + companion object { sealed class Node @@ -39,10 +57,14 @@ class SealedClassTest { interface Factory { fun create(): Node + + fun format(node: Node): String } class FactoryImpl : Factory { override fun create(): Node = Root(0) + + override fun format(node: Node): String = node.toString() } } diff --git a/modules/mockk/src/commonTest/kotlin/io/mockk/it/SealedInterfaceTest.kt b/modules/mockk/src/commonTest/kotlin/io/mockk/it/SealedInterfaceTest.kt index 91f727abf..c946c28e1 100644 --- a/modules/mockk/src/commonTest/kotlin/io/mockk/it/SealedInterfaceTest.kt +++ b/modules/mockk/src/commonTest/kotlin/io/mockk/it/SealedInterfaceTest.kt @@ -2,6 +2,8 @@ package io.mockk.it import io.mockk.every import io.mockk.mockk +import org.junit.jupiter.api.condition.DisabledForJreRange +import org.junit.jupiter.api.condition.JRE import kotlin.test.Test import kotlin.test.assertEquals @@ -30,6 +32,22 @@ class SealedInterfaceTest { assertEquals(Leaf(1), result) } + @Test + @DisabledForJreRange( + min = JRE.JAVA_17, + disabledReason = "https://github.com/mockk/mockk/issues/934" + ) + fun serviceTakesSealedInterfaceAsInput() { + val formattedNode = "Formatted node" + val factory = mockk { + every { format(any()) } answers { formattedNode } + } + + val result = factory.format(Root(0)) + + assertEquals(formattedNode, result) + } + companion object { sealed interface Node @@ -39,10 +57,14 @@ class SealedInterfaceTest { interface Factory { fun create(): Node + + fun format(node: Node): String } class FactoryImpl : Factory { override fun create(): Node = Root(0) + + override fun format(node: Node): String = node.toString() } } From f010fb8e117dd698e15dcff97bd95ebc595e327d Mon Sep 17 00:00:00 2001 From: Cliffred van Velzen Date: Thu, 29 Sep 2022 19:49:09 +0200 Subject: [PATCH 2/3] Fix InstantiationError when using any() where a sealed type is expected --- .../recording/JvmSignatureValueGenerator.kt | 44 ++++++++++++------- 1 file changed, 27 insertions(+), 17 deletions(-) diff --git a/modules/mockk/src/jvmMain/kotlin/io/mockk/impl/recording/JvmSignatureValueGenerator.kt b/modules/mockk/src/jvmMain/kotlin/io/mockk/impl/recording/JvmSignatureValueGenerator.kt index 20a0278e2..e70e4e6b8 100644 --- a/modules/mockk/src/jvmMain/kotlin/io/mockk/impl/recording/JvmSignatureValueGenerator.kt +++ b/modules/mockk/src/jvmMain/kotlin/io/mockk/impl/recording/JvmSignatureValueGenerator.kt @@ -24,24 +24,34 @@ class JvmSignatureValueGenerator(val rnd: Random) : SignatureValueGenerator { return constructor.call(valueSig) } - return cls.cast( - when (cls) { - java.lang.Boolean::class -> rnd.nextBoolean() - java.lang.Byte::class -> rnd.nextInt().toByte() - java.lang.Short::class -> rnd.nextInt().toShort() - java.lang.Character::class -> rnd.nextInt().toChar() - java.lang.Integer::class -> rnd.nextInt() - java.lang.Long::class -> rnd.nextLong() - java.lang.Float::class -> rnd.nextFloat() - java.lang.Double::class -> rnd.nextDouble() - java.lang.String::class -> rnd.nextLong().toString(16) + return cls.cast(instantiate(cls, anyValueGeneratorProvider, instantiator)) + } + + private fun instantiate( + cls: KClass, + anyValueGeneratorProvider: () -> AnyValueGenerator, + instantiator: AbstractInstantiator + ): Any = when (cls) { + Boolean::class -> rnd.nextBoolean() + Byte::class -> rnd.nextInt().toByte() + Short::class -> rnd.nextInt().toShort() + Character::class -> rnd.nextInt().toChar() + Integer::class -> rnd.nextInt() + Long::class -> rnd.nextLong() + Float::class -> rnd.nextFloat() + Double::class -> rnd.nextDouble() + String::class -> rnd.nextLong().toString(16) - else -> - @Suppress("UNCHECKED_CAST") - anyValueGeneratorProvider().anyValue(cls, isNullable = false) { - instantiator.instantiate(cls) - } as T + else -> + if (cls.isSealed) { + cls.sealedSubclasses.firstNotNullOfOrNull { + instantiate(it, anyValueGeneratorProvider, instantiator) + } ?: error("Unable to create proxy for sealed class $cls, available subclasses: ${cls.sealedSubclasses}") + } else { + @Suppress("UNCHECKED_CAST") + anyValueGeneratorProvider().anyValue(cls, isNullable = false) { + instantiator.instantiate(cls) + } as T } - ) } } From ea5c646732d07bf8d9beb96e14b56720c91e8c46 Mon Sep 17 00:00:00 2001 From: Cliffred van Velzen Date: Wed, 5 Oct 2022 15:48:32 +0200 Subject: [PATCH 3/3] Remove DisabledForJreRange annotations --- .../src/commonTest/kotlin/io/mockk/it/SealedClassTest.kt | 4 ---- .../src/commonTest/kotlin/io/mockk/it/SealedInterfaceTest.kt | 4 ---- 2 files changed, 8 deletions(-) diff --git a/modules/mockk/src/commonTest/kotlin/io/mockk/it/SealedClassTest.kt b/modules/mockk/src/commonTest/kotlin/io/mockk/it/SealedClassTest.kt index 072ce1346..631532156 100644 --- a/modules/mockk/src/commonTest/kotlin/io/mockk/it/SealedClassTest.kt +++ b/modules/mockk/src/commonTest/kotlin/io/mockk/it/SealedClassTest.kt @@ -33,10 +33,6 @@ class SealedClassTest { } @Test - @DisabledForJreRange( - min = JRE.JAVA_17, - disabledReason = "https://github.com/mockk/mockk/issues/934" - ) fun serviceTakesSealedClassAsInput() { val formattedNode = "Formatted node" val factory = mockk { diff --git a/modules/mockk/src/commonTest/kotlin/io/mockk/it/SealedInterfaceTest.kt b/modules/mockk/src/commonTest/kotlin/io/mockk/it/SealedInterfaceTest.kt index c946c28e1..5001fe6aa 100644 --- a/modules/mockk/src/commonTest/kotlin/io/mockk/it/SealedInterfaceTest.kt +++ b/modules/mockk/src/commonTest/kotlin/io/mockk/it/SealedInterfaceTest.kt @@ -33,10 +33,6 @@ class SealedInterfaceTest { } @Test - @DisabledForJreRange( - min = JRE.JAVA_17, - disabledReason = "https://github.com/mockk/mockk/issues/934" - ) fun serviceTakesSealedInterfaceAsInput() { val formattedNode = "Formatted node" val factory = mockk {