Coroutines Исключение теста не обрабатывается ни с TestCoroutineDispatcher, ни с TestCoroutineScope

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

    private val testDispatcher = TestCoroutineDispatcher()

    @Before
    fun setup() {
        // provide the scope explicitly, in this example using a constructor parameter
        Dispatchers.setMain(testDispatcher)
    }

    @After
    fun cleanUp() {
        Dispatchers.resetMain()
        testDispatcher.cleanupTestCoroutines()
    }

    @Test(expected = RuntimeException::class)
    fun testSomeFunctionWithException() = testDispatcher.runBlockingTest {
        someFunctionWithException()
    }


    private fun someFunctionWithException() {
        MainScope().launch {
            throw RuntimeException("Failed via TEST exception")
        }
    }

Метод тестирования выше и ниже

    private val testScope = TestCoroutineScope()
    private lateinit var subject: Subject

    @Before
    fun setup() {
        // provide the scope explicitly, in this example using a constructor parameter
        subject = Subject(testScope)
    }

    @After
    fun cleanUp() {
        testScope.cleanupTestCoroutines()
    }


    @Test(expected = RuntimeException::class)
    fun testFooWithException() = testScope.runBlockingTest {
        subject.fooWithException()
    }

    class Subject(private val scope: CoroutineScope) {


        fun fooWithException() {
            scope.launch {
                println("fooWithException() thread: ${Thread.currentThread().name}")
                throw RuntimeException("Failed via TEST exception")
            }
        }
    }

оба они терпят крах, хотя

Примечание. Рекомендуется предоставлять TestCoroutineScope, если он не усложняет код, поскольку он также увеличивает количество исключений до ошибок тестирования.

  1. Почему они оба разбиваются?
  2. Почему тот, у кого есть область видимости, не выходит из строя, а не падает?

person Thracian    schedule 11.05.2020    source источник


Ответы (2)


TestCoroutineScope использует TestCoroutineExceptionHandler, который будет обрабатывать все исключения, сгенерированные сопрограммой, собирая их в uncaughtExceptions списке, хотя первое из них будет повторно выбрано во время cleanUp или, более конкретно, когда вызывается cleanupTestCoroutines(), поэтому вам нужно что-то сделать с этим исключением, чтобы предотвратить сбой тесты.

@After
fun cleanUp() {
    try {
        testScope.cleanupTestCoroutines()
    } catch (e: Exception) {
        //Do something here
    }
}

Во время тестов вы можете просмотреть список uncaughtExceptions, чтобы сделать свои утверждения:

@Test(expected = RuntimeException::class)
fun testFooWithException() = testScope.runBlockingTest {
    subject.fooWithException()
    assertEquals(1, uncaughtExceptions.size)
    assertEquals(uncaughtExceptions[0].message, "Failed via TEST exception")
}
person Glenn Sandoval    schedule 11.05.2020
comment
Помещение testScope.cleanupTestCoroutines() внутрь try-catch блока сработало. - person Thracian; 11.05.2020
comment
Тест TestDispatcher все еще вылетает, хотя я поместил его cleanupTestCoroutines внутри try-catch - person Thracian; 11.05.2020

У меня нет среды, в которой я могу легко протестировать следующее, но попробуйте поместить свои блоки runBlocking в тело ваших тестовых функций. Например:

@Test
fun myTest() {
    runBlocking {
        // Do your test stuff here
    }
}

Я обнаружил, что у меня есть проблемы в тестовых примерах, когда я раньше использовал объявление fun myTest() = runBlocking{. Похоже, что средство запуска тестов не может обнаружить выполнение теста без какого-либо утверждения в теле и там, где нет возврата. Что-то подобное.

В любом случае, надеюсь, что это поможет.

person Laurence    schedule 11.05.2020
comment
Спасибо за ваш ответ, он работает, но вопрос здесь в том, чтобы использовать TestCoroutineScope или TestCoroutineDispatcher. Я обновил его, но ответ Гленна решает проблему с помощью TestCoroutineScope - person Thracian; 11.05.2020