unit-testingkotlinmockitokotlintest

how to mock/match lambda in kotlin method signature


I have some code on the follwing form:

@Language("SQL")
val someSql = """
    SELECT foo
    FROM bar 
    WHERE foo = :foo
    """
return session.select(some, mapOf("foo" to foo)) {
    MyObject(
            foo = it.string("foo"),
    )
}.firstOrNull()

which use the below from com.github.andrewoma.kwery.core. Note the lambda in the method signature:

fun <R> select(@Language("SQL") sql: String,
               parameters: Map<String, Any?> = mapOf(),
               options: StatementOptions = defaultOptions,
               mapper: (Row) -> R): List<R> 

I use mockitokotlin2.

I need to return an instance of MyObject when the session select method is called with a select query (containing "SELECT foo").

I was thinking I could pass a mock into the lambda as below (but then it wont match the method call I am trying to mock). The below code is an attempt. But it never matches in eq(function2):

val function2: (Row) -> Int = mock {
    onGeneric { invoke(any()) }.thenReturn(MyObject(foo="test-foo"))
}

val session = mock<Session> {
    on { select(sql = any(), parameters = any(), options = any(), mapper = eq(function2))}.thenReturn(listOf(MyObject(foo="test-foo")))
} 

function2 in my case is not really a mapper, it is not eq to what I am trying to mock, it never matches and the mock is never called.

So what do I put in the mock of session, select instead of eq(function2) in the code above to get MyObject object returned?


Solution

  • I think you just need to specify they type that your mapper is expected to return when setting up the session mock - in your case looks to be Function1<Row, MyObject>

    val session = mock<Session> {
        on { select(sql = anyString(), parameters = anyMap(), options = any(), mapper = any<Function1<Row, MyObject>>())}.thenReturn(listOf(MyObject(foo="test-foo")))
    }