import io.mockk.verify
import org.junit.jupiter.api.Test
class DummyTest {
@Test
fun `dummy test to show issue with mockk`() {
val lambdaFunc: (SomeDataClass) -> Unit = { }
dummyFunc(lambdaFunc)
verify(exactly = 1) {
lambdaFunc(any<SomeDataClass>(any())) // using lambdaFunc(any<SomeDataClass>(any<AnotherDataClass>())) gives Argument type mismatch error
}
}
}
data class AnotherDataClass(val arg1: String, val arg2: String)
sealed class SomeSealedClass {
data class SomeDataClass(val anotherDataClass: AnotherDataClass): SomeSealedClass()
}
fun dummyFunc(
onEvent: (SomeDataClass) -> Unit
) {
onEvent(SomeDataClass(AnotherDataClass("arg1", "arg2")))
}
When I run the above, I get the following error:
Receiver class kotlin.reflect.KClass$Subclass1 does not define or inherit an implementation of the resolved method 'abstract boolean isValue()' of interface kotlin.reflect.KClass.
java.lang.AbstractMethodError: Receiver class kotlin.reflect.KClass$Subclass1 does not define or inherit an implementation of the resolved method 'abstract boolean isValue()' of interface kotlin.reflect.KClass.
at io.mockk.impl.recording.JvmSignatureValueGenerator.signatureValue(JvmSignatureValueGenerator.kt:19)
at io.mockk.impl.recording.states.RecordingState.matcher(RecordingState.kt:46)
at io.mockk.impl.recording.CommonCallRecorder.matcher(CommonCallRecorder.kt:52)
at io.mockk.MockKMatcherScope.match(API.kt:695)
at io.mockk.MockKMatcherScope.any(API.kt:745)
at com.sarim.puzzle.data.usecase.DummyTest.dummy_test_to_show_issue_with_mockk$lambda$0(DummyTest.kt:16)
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.VerifyBlockEvaluator.verify(VerifyBlockEvaluator.kt:30)
at io.mockk.MockKDsl.internalVerify(API.kt:120)
at io.mockk.MockKKt.verify(MockK.kt:218)
at io.mockk.MockKKt.verify$default(MockK.kt:209)
at com.sarim.puzzle.data.usecase.DummyTest.dummy test to show issue with mockk(DummyTest.kt:15)
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)
Most solutions I have seen to this do not deal with nested Data classes. I am not even sure if Mockk supports this kind of verification.
The culprit is here:
verify(exactly = 1) { lambdaFunc(any<SomeDataClass>(any())) // using lambdaFunc(any<SomeDataClass>(any<AnotherDataClass>())) gives Argument type mismatch error }
But I am not sure how to change this line to verify behavior
Okay, I have finally found a way to make this work. I am re-posting the modified version of my code again
import com.sarim.puzzle.data.usecase.SomeSealedClass.SomeDataClass
import com.sarim.puzzle.data.usecase.SomeSealedClass.SomeOtherDataClass
import io.mockk.mockk
import io.mockk.verify
import org.junit.jupiter.api.Test
class DummyTest {
@Test
fun `dummy test to show issue with mockk`() {
val lambdaFunc1: (SomeSealedClass) -> Unit = mockk(relaxed = true)
val lambdaFunc2: (SomeSealedClass) -> Unit = mockk(relaxed = true)
dummyFunc(lambdaFunc1, lambdaFunc2)
verify(exactly = 1) {
lambdaFunc1(
withArg {
it is SomeOtherDataClass && it.arg == "arg"
}
)
}
verify(exactly = 1) {
lambdaFunc2(
withArg {
it is SomeDataClass && it.anotherDataClass.arg1 == "arg1" && it.anotherDataClass.arg2 == "arg2"
}
)
}
}
}
data class AnotherDataClass(val arg1: String, val arg2: String)
sealed class SomeSealedClass {
data class SomeDataClass(val anotherDataClass: AnotherDataClass): SomeSealedClass()
data class SomeOtherDataClass(val arg: String): SomeSealedClass()
}
fun dummyFunc(
onEvent1: (SomeSealedClass) -> Unit,
onEvent2: (SomeSealedClass) -> Unit
) {
onEvent1(SomeOtherDataClass("arg"))
onEvent2(SomeDataClass(AnotherDataClass("arg1", "arg2")))
}
Basically, you need to mock the lambdas and then use withArg to first verify the type of Data Class that you are passing in and, if that data class has further arguments, you can verify those too.