Тестирование сопрограмм
Тестируйте приостанавливаемые функции
«Тестирование сопрограмм» — бесплатный урок Kotlin Academy на CoddyKit. Это урок 4 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Kotlin Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Kotlin Academy содержит 4 уроков всего.
Почему тестирование сопрограмм особенное
Сопрограммы выполняются асинхронно и могут использовать задержки. Тестам нужны контролируемое время и способ дождаться завершения приостанавливаемых функций.
Библиотека kotlinx-coroutines-test предоставляет именно это.
Добавление библиотеки для тестов
Добавьте артефакт для тестирования сопрограмм в зависимости тестов.
dependencies {
testImplementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:1.8.1")
}runTest
runTest — точка входа. Она выполняет тело теста-сопрограммы и автоматически дожидается завершения всех дочерних сопрограмм.
import kotlinx.coroutines.test.runTest
import org.junit.jupiter.api.Test
class FetchTest {
@Test
fun fetches() = runTest {
// suspend calls allowed here
}
}Виртуальное время
Внутри runTest вызовы delay пропускаются с использованием виртуального времени. Задержка в 10 секунд завершается мгновенно, сохраняя порядок выполнения.
import kotlinx.coroutines.delay
import kotlinx.coroutines.test.runTest
// runTest {
// delay(10_000) // returns immediately
// }Ручное продвижение времени
Планировщик тестов позволяет намеренно продвигать время с помощью advanceTimeBy и выполнять ожидающую работу с помощью runCurrent.
import kotlinx.coroutines.test.runTest
import kotlinx.coroutines.test.advanceTimeBy
import kotlinx.coroutines.test.runCurrent
// runTest {
// launch { delay(1000); println("done") }
// advanceTimeBy(1000)
// runCurrent()
// }Диспетчеры для тестов
StandardTestDispatcher ставит сопрограммы в очередь, пока вы не продвинете время. UnconfinedTestDispatcher выполняет их сразу. Выбирайте диспетчер в зависимости от необходимого уровня контроля.
import kotlinx.coroutines.test.StandardTestDispatcher
import kotlinx.coroutines.test.UnconfinedTestDispatcher
val standard = StandardTestDispatcher()
val unconfined = UnconfinedTestDispatcher()Внедрение диспетчера
Рабочий код должен принимать диспетчер, а не жёстко задавать Dispatchers.IO. Тогда тесты смогут внедрять диспетчер для тестов.
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
class Service(private val io: CoroutineDispatcher = Dispatchers.IO) {
suspend fun load(): String = withContext(io) { "data" }
}Замена Dispatchers.Main
В коде в стиле Android замените главный диспетчер с помощью Dispatchers.setMain(testDispatcher), а после этого сбросьте замену.
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.test.setMain
import kotlinx.coroutines.test.resetMain
import kotlinx.coroutines.test.StandardTestDispatcher
// Dispatchers.setMain(StandardTestDispatcher())
// ... test ...
// Dispatchers.resetMain()Тестирование приостанавливаемой функции
Приостанавливаемую функцию можно напрямую вызвать и проверить внутри runTest.
import kotlinx.coroutines.delay
import kotlinx.coroutines.test.runTest
import org.junit.jupiter.api.Assertions.assertEquals
suspend fun compute(): Int { delay(1000); return 42 }
// @Test fun computes() = runTest {
// assertEquals(42, compute())
// }Тестирование потоков
Соберите значения из Flow и проверьте их. Библиотека Turbine особенно упрощает тестирование потоков.
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.toList
import kotlinx.coroutines.test.runTest
import org.junit.jupiter.api.Assertions.assertEquals
// @Test fun emits() = runTest {
// val values = flowOf(1, 2, 3).toList()
// assertEquals(listOf(1, 2, 3), values)
// }Рабочий фрагмент сопрограммы
За пределами тестов runBlocking связывает приостанавливаемый код с обычной функцией main. Это показывает приостанавливаемую функцию, которую необходимо протестировать.
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.delay
suspend fun compute(): Int { delay(100); return 42 }
fun main() = runBlocking {
println(compute())
}Быстрая проверка
Приостанавливаемая функция вызывает delay(5000). Почему тест с использованием runTest завершается почти мгновенно?
Повторение
Вы умеете надёжно тестировать сопрограммы:
runTestвыполняет приостанавливаемый код и дожидается дочерних сопрограмм- Виртуальное время пропускает задержки; при необходимости продвигайте его вручную
- Внедряйте диспетчеры; используйте
setMain/resetMain - Тестируйте потоки, собирая их значения (или с помощью Turbine)
На этом курс по тестированию завершен.
Часто задаваемые вопросы
Урок «Тестирование сопрограмм» бесплатный?
Да — полный текст урока «Тестирование сопрограмм» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Kotlin Academy, подпишись на CoddyKit PRO. Курс Kotlin Academy содержит 4 уроков всего.
Чему я научусь в уроке «Тестирование сопрограмм»?
Тестируйте приостанавливаемые функции Ты практикуешь Kotlin Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать Kotlin Academy?
Предыдущий опыт не требуется. Kotlin Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 4 из 4.
Сколько времени занимает урок «Тестирование сопрограмм»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке Kotlin Academy?
Да. Каждый урок Kotlin Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- Написание тестов с JUnit5
- Проверки
- Имитация с MockK
- Тестирование сопрограмм