Юнит-тестирование сопрограмм Kotlin с runBlocking не ждет выполнения - PullRequest
0 голосов
/ 06 января 2019

Есть ли способ дождаться приостановки функции, которая выполняется в области, например, что делает runBlocking для запуска функций приостановки?

Например,

class CoroutineTestCase : CoroutineScope {
    val job = Job()
    var value = 1
    override val coroutineContext: CoroutineContext
        get() = job + Dispatchers.Unconfined


    fun testFunction() {
         async {
             delay(2000)
             value = 2
        }
    }
}

@Test
fun testCoroutine() = runBlocking {
    val coroutineTestCase = CoroutineTestCase()
    coroutineTestCase.testFunction()
    assertEquals(2, coroutineTestCase.value)
}

Вышеприведенный тест завершается неудачно со значением 1 и не изменяется (так как launch не ожидался до конца). Если бы testFunction была приостановленной функцией, и я запустил ее с помощью runBlocking внутри моего модульного теста, все бы сработало.

Я пробовал с другими пользовательскими диспетчерами (такими как тот, что ниже), которые могут блокировать выполнение своих задач, но не повезло

class TestUiContext : CoroutineDispatcher() {
     override fun dispatch(context: CoroutineContext, block: Runnable) {
         block.run()
    }
}

1 Ответ

0 голосов
/ 06 января 2019

Хорошо, я понял, что происходит. Запуск не ожидается, поскольку его возвращаемое значение никогда не используется.

В приведенном выше примере testFunction должно возвращать возвращаемое значение launch, которое является Deffered объектом, который можно ожидать / присоединять. Таким образом, чтобы фактически дождаться его завершения, необходимо изменить код, как показано ниже:

class CoroutineTestCase : CoroutineScope {
    val job = Job()
    var value = 1
    override val coroutineContext: CoroutineContext
        get() = job + Dispatchers.Unconfined


    fun testFunction(): Deferred<Unit> {
         return async {
                 delay(20000)
                 value = 2
        }
    }
}

@Test
fun testCoroutine() = runBlocking {
    val coroutineTestCase = CoroutineTestCase()
    coroutineTestCase.testFunction().await()
    assertEquals(2, coroutineTestCase.value)
}

В настоящее время единственная проблема заключается в том, что в этом случае фактически задерживается на 20 секунд (с неограниченным диспетчером).

...