Martin Mlostek
Martin Mlostek

Reputation: 2970

Unit test for Kotlin lambda callback

Let's say we have the following function to test

fun loadData(dataId: Long, completion: (JsonElement?, Exception?) -> Unit) {
    underlayingApi.post(url = "some/rest/url",
            completion = { rawResult, exception ->
                val processedResult = processJson(rawResult)
                completion(processedResult, exception)
            })
}

It's clear to me how to mock, inject, stub and verify the calls to underlayingApi.

How to verify the result returned via completion(processedResult, exception)?

Upvotes: 21

Views: 16197

Answers (2)

Sebastian
Sebastian

Reputation: 2956

Building on Martin's answer, here is my approach without lint warnings:

import com.nhaarman.mockito_kotlin.*

@Test
fun loadData() {
    val mockUnderlyingApi: UnderlayingApi = mock()
    val underTest = ClassBeingTested()
    underTest.underlayingApi = mockUnderlyingApi

    whenever(mockUnderlyingApi.post(eq("some/rest/url"), any())).thenAnswer {
        val completion = it.getArgument<((rawResult: String?, exception: Exception?) -> Unit)>(1)
        completion.invoke("result", null)
    }

    underTest.loadData(0L,
            { jsonElement, exception ->
                // Check whatever you need to check
                // on jsonElement an/or exception
            })
}

Upvotes: 10

Martin Mlostek
Martin Mlostek

Reputation: 2970

To test the lambdas behavior, the underlayingApi has to be mocked where the lambda is invoked via the InvoactionOnMock object like this.

    `when`(underlayingApi.post(eq("some/rest/url"),
                               any())).thenAnswer {
        val argument = it.arguments[1]
        val completion = argument as ((rawResult: String?, exception: Exception?) -> Unit)
        completion.invoke("result", null)
    }

This leads to the invocation of the callback within the object under test. Now to check if the callback out of the object under test is working verify it like that.

    objUnderTest.loadData(id,
                          { json, exception ->
                              assert....
                          })

Upvotes: 17

Related Questions