在 kotlin 中,如何模拟包装回调的挂起函数?
In kotlin, how do I mock a suspend function that wraps a callback?
假设有一个带有回调的接口:
interface SomeInterface {
fun doSomething(arg: String, callback: (Exception?, Long) -> Unit)
}
我将其扩展为这样的挂起函数:
suspend fun SomeInterface.doSomething(arg: String): Long = suspendCoroutine { cont ->
this.doSomething(arg) { err, result ->
if (err == null) {
cont.resume(result)
} else {
cont.resumeWithException(err)
}
}
}
我想在测试中对此进行模拟,但失败了。
理想情况下,我想使用这样的东西:
@Test
fun checkService() {
runBlocking {
val myService = mock<SomeInterface>()
whenever(myService.doSomething(anyString())).thenReturn(1234L)
val result = myService.doSomething("")
assertEquals(result, 1234L)
}
}
上面的语法因模拟异常而失败,因为它需要回调的匹配器。
org.mockito.exceptions.misusing.InvalidUseOfMatchersException:
Invalid use of argument matchers!
2 matchers expected, 1 recorded:
如何模拟这样的挂起函数?
如果无法使用类似的语法,我如何使用所需的参数进行模拟回调,以便在我的代码中使用的挂起变体 returns 在测试期间获得所需的结果?
更新:
当它是扩展功能时似乎是不可能的。根据 Marko Topolnik 的评论,我认为这是因为扩展只是一个静态函数,超出了 mockito 的能力。
当 suspend 函数是一个成员函数时,它会按预期工作,使用我的原始语法。
这里有一些演示代码的要点:
https://gist.github.com/mirceanis/716bf019a47826564fa57a77065f2335
我建议您使用 MockK 进行测试,这样对协程更友好。
要模拟协程,您可以使用 coEvery
和 returns
,如下所示:
val interf = mockk<SomeInterface>()
coEvery { a.doSomething(any()) } returns Outcome.OK
当你需要的时候
on .... do return ..
并且方法被暂停,使用 mockito 你可以使用这个:
- 使用这个库mockito-kotlin
- 模拟您的对象,让我们将其命名为 myObject(myObject 具有名为 isFoo 的挂起方法)
然后:
myObject.stub {
onBlocking { isFoo() }.doReturn(true)
}
假设有一个带有回调的接口:
interface SomeInterface {
fun doSomething(arg: String, callback: (Exception?, Long) -> Unit)
}
我将其扩展为这样的挂起函数:
suspend fun SomeInterface.doSomething(arg: String): Long = suspendCoroutine { cont ->
this.doSomething(arg) { err, result ->
if (err == null) {
cont.resume(result)
} else {
cont.resumeWithException(err)
}
}
}
我想在测试中对此进行模拟,但失败了。 理想情况下,我想使用这样的东西:
@Test
fun checkService() {
runBlocking {
val myService = mock<SomeInterface>()
whenever(myService.doSomething(anyString())).thenReturn(1234L)
val result = myService.doSomething("")
assertEquals(result, 1234L)
}
}
上面的语法因模拟异常而失败,因为它需要回调的匹配器。
org.mockito.exceptions.misusing.InvalidUseOfMatchersException:
Invalid use of argument matchers!
2 matchers expected, 1 recorded:
如何模拟这样的挂起函数? 如果无法使用类似的语法,我如何使用所需的参数进行模拟回调,以便在我的代码中使用的挂起变体 returns 在测试期间获得所需的结果?
更新: 当它是扩展功能时似乎是不可能的。根据 Marko Topolnik 的评论,我认为这是因为扩展只是一个静态函数,超出了 mockito 的能力。
当 suspend 函数是一个成员函数时,它会按预期工作,使用我的原始语法。
这里有一些演示代码的要点: https://gist.github.com/mirceanis/716bf019a47826564fa57a77065f2335
我建议您使用 MockK 进行测试,这样对协程更友好。
要模拟协程,您可以使用 coEvery
和 returns
,如下所示:
val interf = mockk<SomeInterface>()
coEvery { a.doSomething(any()) } returns Outcome.OK
当你需要的时候
on .... do return ..
并且方法被暂停,使用 mockito 你可以使用这个:
- 使用这个库mockito-kotlin
- 模拟您的对象,让我们将其命名为 myObject(myObject 具有名为 isFoo 的挂起方法)
然后:
myObject.stub {
onBlocking { isFoo() }.doReturn(true)
}