android - 如何使用回调对挂起函数进行单元测试
问题描述
我有以下代码:
suspend fun initialize(sdk: Sdk) =
suspendCoroutine<Unit> { continuation ->
try {
sdk.initialize(
callback = { continuation.resume(Unit) },
onFailure = { error -> continuation.resumeWithException(SdkException(error.message)) })
} catch (exception: Exception) {
continuation.resumeWithException(
SdkException("Crash inside SDK", exception)
)
}
}
Sdk 是一个第三方库。我suspendCoroutine
用来暂停协程并在 sdk 完成初始化时恢复。一切正常,但是当我尝试编写这样的单元测试时,我得到以下结果IllegalStateException: This job has not completed yet
。我正在使用mockito-kotlin编写以下测试:
@Test
fun `should initialize sdk correctly`() = runBlockingTest {
val sdk = mock<Sdk>()
initializeSdk(sdk)
verify(sdk).initialize(any(), any())
}
基本上我想做的是能够测试resume
和resumeWithException
解决方案
就个人而言,我不是模拟的粉丝。如果Sdk
是一个接口,您可以只提供自己的测试实现来执行您的测试(用于成功和错误结果)。您可以准确控制何时/是否调用回调等。
如果 Sdk 是一个你无法控制的类,你可以创建一个接口来抽象这个Sdk
类,并让你的initialize
方法使用你自己的接口。但是我不得不承认这并不理想。
如果您坚持使用模拟,通常模拟库可以让您使用调用参数来模拟对方法调用的响应。使用 Mockito,它应该是这样的:
val sdk = mock<Sdk> {
on { initialize(any(), any()) } doAnswer { invocation ->
@Suppress("UNCHECKED_CAST")
val successCallback = invocation.arguments[0] as (() -> Unit) // use callback's function type here
successCallback.invoke()
}
}
(虽然我不是 Mockito 方面的专家,所以可能有更简洁或类型安全的方法:D)
推荐阅读
- sql - Oracle中如何对关联表的属性进行索引?
- c# - 如何在 C#.Net 中实现 Google Place API
- html - 渲染后如何找到 Mat-Table 的宽度?
- javascript - 如何从 javascript 类继承 typescript 类
- arduino - Arduino FastLED:尝试将 LED 组合成两对
- python - Python:前导下划线表示私有是否包括同一类的其他实例?
- c# - 公共静态类 Contract && .net core 3.1 && macOS
- ios - Previos 路线未从地图中删除:HERE IOS - Swift SDK
- android - Flutter如何将消息传递给Android AlarmManager创建的isolate
- python - 有没有办法根据用户在输入中写入的数字来决定 x 打印变量 x 次?[Python 3.8]