Aldo Wachyudi
Aldo Wachyudi

Reputation: 17991

How to mock and verify Lambda expression in Kotlin?

In Kotlin (and Java 8) we can use Lambda expression to remove boilerplate callback interface. For example,

data class Profile(val name: String)

interface ProfileCallback {
  fun onSuccess(profile: Profile)
}

class ProfileRepository(val callback: ProfileCallback) {

  fun getProfile() {
    // do calculation
    callback.onSuccess(Profile("name"))
  }
}

We can change remove ProfileCallback and change it into Kotlin's Lambda:

class ProfileRepository(val callback: (Profile) -> Unit) {

  fun getProfile() {
    // do calculation
    callback(Profile("name"))
  }
}

This works fine, but I'm not sure how to mock and then verify that function. I have tried using Mockito like this

@Mock
lateinit var profileCallback: (Profile) -> Unit

@Test
fun test() {
    // this wouldn't work
    Mockito.verify(profileCallback).invoke(any())   
}

but it throw an Exception:

org.mockito.exceptions.base.MockitoException: ClassCastException occurred while creating the mockito mock : class to mock : 'kotlin.jvm.functions.Function1', loaded by classloader : 'sun.misc.Launcher$AppClassLoader@7852e922'

How to mock and verify Lambda expression in Kotlin? Is it even possible?

Upvotes: 8

Views: 8672

Answers (1)

Oleksandr Papchenko
Oleksandr Papchenko

Reputation: 2211

Here is example how you can achieve that using mockito-kotlin:

Given repository class

class ProfileRepository(val callback: (Int) -> Unit) {

    fun getProfile() {
        // do calculation
        callback(1)
    }
}

Using mockito-kotlin lib - you can write test mocking lambdas like this:

@Test
fun test() {
    val callbackMock: (Int) -> Unit = mock()
    val profileRepository = ProfileRepository(callbackMock)

    profileRepository.getProfile()

    argumentCaptor<Int>().apply {
        verify(callbackMock, times(1)).invoke(capture())
        assertEquals(1, firstValue)
    }
}

Upvotes: 6

Related Questions