单元测试 CoroutineExceptionHandler
Unit Testing CoroutineExceptionHandler
您好,我有这段使用协程的代码,我想对其进行单元测试:
我的问题是我的异常从未被 CoroutineExceptionHandler
.
捕捉到
我的代码如下所示:
fun request() {
val handler = CoroutineExceptionHandler { _, throwable -> liveData.value = Resource.error(throwable.message) }
viewModelScope.launch(handler) {
liveData.value = Resource.loading()
val result = withContext(Dispatchers.IO) { useCase.request() }
liveFdDetails.value = Resource.success(result)
}
}
还有我的测试:
fun testError() = runBlocking {
//Given
val observer: Observer<Resource<Data>> = mock()
whenever(useCase.request()).thenThrow(Error("MSG"))
viewModel.liveData.observeForever(observer)
//When
viewModel.request()
//Then
inOrder(observer).apply {
verify(observer).onChanged(Resource.loading())
verify(observer).onChanged(Resource.error("MSG"))
}
}
viewModelScope.launch(handler) {
此处您在 runBlocking
以外的范围内启动协程。由于它不是它的子协程,runBlocking
不会等待它完成。很可能整个测试在协程有时间在 IO 线程中启动并失败之前完成。
但是,考虑到您在异常处理程序中的代码,我认为您没有使用正确的工具。
协程异常处理程序不是用于常规异常处理的机制,它们只是一种 last-resort 措施,用于有机会观察您的代码应该处理的异常,但由于错误。
对于业务logic-level错误处理,使用自然机制try-catch
。如果你有很多重复的错误处理逻辑,你总是可以写一个 inline fun(block: inline () -> Unit)
将块包装在这样的样板中 try-catch.
您好,我有这段使用协程的代码,我想对其进行单元测试:
我的问题是我的异常从未被 CoroutineExceptionHandler
.
我的代码如下所示:
fun request() {
val handler = CoroutineExceptionHandler { _, throwable -> liveData.value = Resource.error(throwable.message) }
viewModelScope.launch(handler) {
liveData.value = Resource.loading()
val result = withContext(Dispatchers.IO) { useCase.request() }
liveFdDetails.value = Resource.success(result)
}
}
还有我的测试:
fun testError() = runBlocking {
//Given
val observer: Observer<Resource<Data>> = mock()
whenever(useCase.request()).thenThrow(Error("MSG"))
viewModel.liveData.observeForever(observer)
//When
viewModel.request()
//Then
inOrder(observer).apply {
verify(observer).onChanged(Resource.loading())
verify(observer).onChanged(Resource.error("MSG"))
}
}
viewModelScope.launch(handler) {
此处您在 runBlocking
以外的范围内启动协程。由于它不是它的子协程,runBlocking
不会等待它完成。很可能整个测试在协程有时间在 IO 线程中启动并失败之前完成。
但是,考虑到您在异常处理程序中的代码,我认为您没有使用正确的工具。
协程异常处理程序不是用于常规异常处理的机制,它们只是一种 last-resort 措施,用于有机会观察您的代码应该处理的异常,但由于错误。
对于业务logic-level错误处理,使用自然机制try-catch
。如果你有很多重复的错误处理逻辑,你总是可以写一个 inline fun(block: inline () -> Unit)
将块包装在这样的样板中 try-catch.