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)
}
}
上述语法因mockito异常而失败,因为它期待回调使用匹配器.
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.
以下是一些演示代码的要点: