Let's say there's an interface with a callback:
interface SomeInterface {
fun doSomething(arg: String, callback: (Exception?, Long) -> Unit)
}
which I extend into a suspend function like this:
suspend fun SomeInterface.doSomething(arg: String): Long = suspendCoroutine { cont ->
this.doSomething(arg) { err, result ->
if (err == null) {
cont.resume(result)
} else {
cont.resumeWithException(err)
}
}
}
I'd like to mock this in tests, but am failing. Ideally I'd like to use something like this:
@Test
fun checkService() {
runBlocking {
val myService = mock<SomeInterface>()
whenever(myService.doSomething(anyString())).thenReturn(1234L)
val result = myService.doSomething("")
assertEquals(result, 1234L)
}
}
The above syntax fails with a mockito exception because it's expecting a matcher for the callback.
org.mockito.exceptions.misusing.InvalidUseOfMatchersException:
Invalid use of argument matchers!
2 matchers expected, 1 recorded:
How can I mock a suspend function like that? If a similar syntax is not possible how can I have the mock call back with the desired arguments such that the suspend variant that is used throughout my code returns the desired result during tests?
Update: It seems it's not possible when it's an extension function. Based on Marko Topolnik's comment, I gather it's because an extension is simply a static function which is out of mockito's capability.
When the suspend function is a member function, then it works as expected, with my original syntax.
Here is a gist with some demo code: https://gist.github.com/mirceanis/716bf019a47826564fa57a77065f2335
suspend fun
s declare at the class file level. Try providing it with an emptyContinuation
. – Fulkwhenever(myService.doSomething(anyString(), any(Continuation.class))
– Fulkany<Continuation<Long>>()
. Also, if I useany()
for the second param, then the.thenReturn(1234L)
doesn't work since it's expectingUnit
, notLong
If I add a second param there, I'm basically mocking the original interface call, not the suspend function. – Overcriticalpublic static
Java method in the compiled class. You won't be able to mock it. However, there are ways to mock the original with more complexity than justthenReturn
. – FulkdoAnswer(Answer).when(...)
– Fulk