单元测试 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.