kotlinunit-testingmockingmockkmockk-verify

Mockk how to verify that a method accepting constructor lambda is invoked


Hey there I am having issues with method accepting constructor type of lambda with following signature:

    class EventLog() {
       inline fun log(block: Builder.() -> Unit) = Builder(logger.atInfo()).apply(block).build().log()
    }

My unit test includes the following fragment:

 mockkStatic(::eventLogger)
 every { eventLogger.log (
            any<com.tlx.bundling.common.logging.Logger.Builder.()-> Unit>()
        )} returns Unit

My end goal is to verify that eventLogger.log() { whatever } is invoked at least 1 time.

this code is throwing exception:

Receiver class kotlin.jvm.functions.Function1$Subclass1 does not define or inherit an implementation of the resolved method 'abstract java.lang.Object invoke(java.lang.Object)' of interface kotlin.jvm.functions.Function1. java.lang.AbstractMethodError: Receiver class kotlin.jvm.functions.Function1$Subclass1 does not define or inherit an implementation of the resolved method 'abstract java.lang.Object invoke(java.lang.Object)' of interface kotlin.jvm.functions.Function1. at com.tlx.bundling.subscriber.adapters.iqiyi.IQIYIubscriberManagerTest$1$2.invokeSuspend$lambda$0(IQIYIubscriberManagerTest.kt:170) 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)


Solution

  • Inline functions are inlined. This means that there isn't actually a call when you write eventLogger.log { ... }. Instead, the compiler replaces that call with the body of log - i.e. Builder(logger.atInfo()).apply { ... }.build().log().

    So to check for a call to log, you actually need to check every call in Builder(logger.atInfo()).apply { ... }.build().log(). And you cannot distinguish a call to log from someone literally writing Builder(logger.atInfo()).apply { ... }.build().log() in their code.

    Or, you can just remove inline.