How can we mock lambdas in Kotlin? Eg. `(T) -> ...
# announcements
c
How can we mock lambdas in Kotlin? Eg.
(T) -> Unit
l
Yes, here's the manual way:
{ t -> }
1
👍 1
p
#C9EJFT6DB
👍 1
c
I'm trying to understand how do I use
when
then
for mocking lambdas. I see
doAnswer
on the web but need more information.
I want to test the
Presenter
. The function in my
Presenter
looks like this:
Copy code
override fun search(query: String) {
        interactor.search(query) { model ->
            view.render(searchState(model))
        }
    }
Copy code
interface Interactor {
        fun search(query: String, publish: (SearchModel) -> Unit)
}
g
I don’t think that one need mocking there. What exactly do you want to check? You can check that interactor method is called and you can return some value for model
c
I want to perform a whenever thenReturn on this method containing lambda
g
Just add implementation to lambda, why do you need mocking here?:
Copy code
val myMockLambda = { model ->
   return when(model) {
      model.something() -> someResult
      model.anythingElse() -> anotherResult
   }
}
I would use this approach, but nothing prevent you from mocking lambda, it’s just an interface under the hood
c
Coz the function returns Unit and I cannot return Void for mocking
g
Return Unit instead
c
Yea, Unit doesn't work either
g
do you use Mockito?
c
Yes
c
Ok lemme try this. Thanks 🙂
Copy code
val publish = mock<(SearchModel) -> Unit>()

whenever(interactor.search("", publish)).thenReturn(publish.invoke(SearchModel.Init))
Getting
UnfinishedStubbingException
here
g
hmm? You use mocking in a wrong way.
whenever is like template
and this method called by presenter
You can do something like:
Copy code
val interactor = mock<MyInteractor>()
whenever(interactor.search("", any())).thenReturn(SearchModel.Init)
c
Copy code
@Test
    fun search() {
        val publish = mock<(SearchModel) -> Unit>()

        whenever(interactor.search("", publish)).doAnswer { publish(SearchModel.Init) }

        presenter.search("")

        verify(view).render(SearchState.Init)
    }
g
No, it’s wrong. Check documentation of
whenever
I don’t understand why do you need mock
publish
at all in this case
if you just want to return something from lambda just return it, using mocking or manually
c
the search function takes in a lambda and I want to return some value from it
g
Could you show some minimal example, how you presenter work, You problem that lambda passed to interactor is passed from presenter
I think your problem is not in mockito or in lambda that returns Unit
Try to write minimal example and I can try to help you, now looks like you on a wrong way
c
Copy code
override fun search(query: String) {
        interactor.search(query) { model ->
            view.render(model.state())
        }
    }
I want to test this function
The callback is returned from the interactor ie of type
(SearchModel) -> Unit
g
Copy code
class SimpleInteractor : Interactor {
  override fun search(query: String, lambda: (SearchModel) -> Unit) {
      lambda(SearchModel.Init)
   }
}
Maybe this simple interactor can help you?
c
Yes this is how I've implemented my interactor
g
That just call your callback
also, you can improve it and pass required state
So why you need mocking?
c
Maybe not. I want to mock
interactor.search(query: String, (SearchModel) -> Unit)
g
for what?
c
Because the presenter calls it and interactor is being mocked
g
but why? I mean just pass this SimpleInteractor to presenter
looks like your test check view state
you do not check Interactor
c
May I DM you the github code reference?
g
would be better to provide some self contained sample, but you try show you existing code
c
Thanks! That'd be really helpful 🙂