'How can Mockito mock a Kotlin `use` (aka try-with-resource)?

If I were trying to add mocks to the following code (where the MyTypeBuilder is mocked to return a mocked MyType - which implements Closeable):

myTypeBuilder.build(myTypeConfiguration).use { myType ->
    myType.callMyMethod()
}

Then trying to verify interactions with myType.callMethod() something like:

myType: MyType = mock()
myTypeBuilder: MyTypeBuilder = mock()
whenever(myTypeBuilder.build(any())).thenReturn(myType)
doMethodCall()
verify(myType, times(1)).callMyMethod()

I'm getting errors:

Wanted but not invoked:
myType.callMethod()
-> at package.me.MyType.callMyMethod(MyType.kt:123)

However, there was exactly 1 interaction with this mock:
myType.close()
-> at kotlin.io.CloseableKt.closeFinally(Closeable.kt:57)

So it appears that I need to add a whenever to execute the use block, but I'm not sure what that should look like. Alternatively, the use should act like a Mockito spy rather than a mock, but then allow mocking on the other methods.



Solution 1:[1]

I tried to reconstruct the error by writing the following code which is basically what you wrote in your question plus some println statements and some boilerplate to make it runnable:

import org.junit.jupiter.api.Test
import org.mockito.Mockito.*
import org.mockito.kotlin.any
import org.mockito.kotlin.mock
import org.mockito.kotlin.whenever
import java.io.Closeable

open class MyTypeBuilder {
    open fun build(config: Any): MyType {
        println("build")
        return MyType()
    }

}

open class MyType : Closeable {

    fun callMyMethod() {
        println("callMyMethod")
    }

    override fun close() {
        println("close")
    }
}

val myTypeConfiguration: Any = "heyho"

fun call(myTypeBuilder: MyTypeBuilder) {
    myTypeBuilder.build(myTypeConfiguration).use { myType ->
        println("call")
        myType.callMyMethod()
    }
}

class MockAndUseTest {

    @Test
    fun test() {
        val myType: MyType = mock()
        val myTypeBuilder: MyTypeBuilder = mock()
        whenever(myTypeBuilder.build(any())).thenReturn(myType)
        call(myTypeBuilder)
        verify(myType, times(1)).callMyMethod()
    }
}

When I run the test case test, it succeeds and is green.

So, unfortunately whatever may cause your problem, it is not contained in the details given by your question.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1