Модульное тестирование CoroutineExceptionHandler - PullRequest
1 голос
/ 17 мая 2019

Здравствуйте, у меня есть этот код, который использует сопрограммы, и я хочу выполнить его модульное тестирование:

Моя проблема в том, что мое исключение никогда не перехватывается 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"))
    }
}

1 Ответ

1 голос
/ 17 мая 2019
viewModelScope.launch(handler) {

Здесь вы запускаете сопрограмму с родительской работой. Исключение, которое избегает его, распространяется в родительское задание, поэтому в этот момент оно не характеризуется как «необработанное».

Обработчики исключений Coroutine не являются механизмом для вашей обычной обработки исключений, они являются лишь крайней мерой, чтобы иметь возможность наблюдать исключение, которое ваш код должен был обработать, но не из-за ошибки.

Для обработки ошибок на уровне бизнес-логики используйте естественный механизм try-catch. Если у вас много повторяющейся логики для обработки ошибок, вы всегда можете написать inline fun(block: inline () -> Unit), который оборачивает блок в такой шаблонный try-catch.

...