[英]How to unit test kotlin coroutine with nested suspended functions
下面是我试图进行单元测试的一段代码。 async(CommonPool)
之前的代码是第一个挂起函数是可测试的,但在此之后,测试仍然失败。 我尝试使用runBlocking
但无论如何都无法测试嵌套的挂起异步函数。
interface Listener {
fun onLoading(user: User?)
fun onSuccess(user: User)
}
execute(listener: Listener) {
listener.onLoading(null)
val service = UserService.getInstance(context, "someurl")
val database = UserDatabase.getInstance(context)
launch(UI) {
val user = async(CommonPool) {
userDatabase.getUser()
}.await()
listener.onLoading(user)
val response = service.getUsersSelf(oauthToken).await()
async(CommonPool) {database.saveUser(userResponse.data.user)}.await()
val user = async(CommonPool) {database.getUser()}.await()
listener.onSuccess(user)
}
}
下面是我的单元测试,我使用mockito来模拟我的监听器并检查交互次数。
@Test
fun execute() {
runBlocking {
userDatabase.saveUser(user)
val listener = mock(GetUser.Listener::class.java)
getUser.execute(listener)
verify(listener, times(1)).onLoading(null) // Success
verify(listener, times(1)).onLoading(user) // Fails
verify(listener, times(1)).onSuccess(user) // Fails
}
}
但最后两次verify
测试失败。 任何人都可以帮我测试吗?
您的execute
是一个即发即弃的功能。 如果这是通过线程完成的,那么它将是Thread { <code> }.start()
并完全放弃对线程的引用。 您唯一剩下的就是Listener
实例,它将在调用完成时得到通知 - 但不会出现错误。
虽然我怀疑这是一个使用协同程序的好方法,它们都是关于消除像Listener
这样的回调接口,如果你知道这种方法对你有好处,那么监听器是你发起的协程中发生事件的唯一方法。
因此,您必须在侦听器中实现单元测试逻辑。 如果没有失败回调,您可能需要等待一段有限的时间来调用方法。 一种方法:
fun execute() {
val latch = CountDownLatch(3)
runBlocking {
val x = object : Listener {
override fun onLoading(user: User?) {
if (user == null) {
require(latch.count == 3L)
latch.countDown()
} else {
require(latch.count == 2L)
latch.countDown()
}
}
override fun onSuccess(user: User) {
require (latch.count == 1L)
latch.countDown()
}
}
}
require(latch.await(10, TimeUnit.SECONDS))
}
您可以使用依赖注入在测试时使用Dispatchers.Unconfined
替换UI Dispatcher。 此测试成功:
@Test
fun test() {
var result = false
GlobalScope.launch (Dispatchers.Unconfined) {
async(Dispatchers.Unconfined) {
sleep(1000)
result = true
}.await()
}
assertTrue(result)
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.