lupuuss / Mokkery

The mocking library for Kotlin Multiplatform, easy to use, boilerplate-free and compiler plugin driven.
https://mokkery.dev
Apache License 2.0
126 stars 7 forks source link

MockMode.autoUnit does not work when mocking functional types #19

Open marchuk0 opened 6 days ago

marchuk0 commented 6 days ago

AutoUnit does not work for functional types.

The first test from the example below will fail, while the second one is successful.

Kotlin multiplatform version: 1.9.24 Kotlin multiplatform target: js Mokkery version: 1.9.24-1.7.0

interface TestInterface {
    fun invokeInterface(foo: Int)
}

class Example {

    @Test
    fun testAutoUnitDoesNotWorkForFunction() {
        val functionMock = mock<(foo: Int) -> Unit>(MockMode.autoUnit)
        functionMock.invoke(1) // Fails with CallNotMockedException: Call Function1(1).invoke(p1 = 1) not mocked!
    }

    @Test
    fun testAutoUnitWorkForInterface() {
        val functionMock = mock<TestInterface>(MockMode.autoUnit)
        functionMock.invokeInterface(1) // success
    }
}
lupuuss commented 4 days ago

It's not really a bug, but a missing feature. Generics in Kotlin are mostly compile time feature and are naturally erased at runtime. Functional types are also generics. Any functional type is treated as (...) -> Any?. This is why autoUnit does not work properly with generics (functions included).

With compiler plugin capabilities it should possible to preserve information about type arguments and improve the way autoUnit works. I will investigate it. Thank you for reporting the issue!