Проблема, с которой вы столкнулись, связана не с runBlocking, а с LiveData, не передающим значение без подключенного наблюдателя.
Я видел много способов справиться с этим, но самое простое - просто использовать observeForever
и CountDownLatch
.
@Test
fun testSomething() {
runBlocking {
viewModel.doSomething()
}
val latch = CountDownLatch(1)
var result: String? = null
viewModel.myLiveData.observeForever {
result = it
latch.countDown()
}
latch.await(2, TimeUnit.SECONDS)
assertNotNull(result)
}
Этот шаблон довольно распространен, и вы, вероятно, увидите множество проектов с некоторым его изменением в виде функции / метода в некотором классе / файле тестовой утилиты, например,
@Throws(InterruptedException::class)
fun <T> LiveData<T>.getTestValue(): T? {
var value: T? = null
val latch = CountDownLatch(1)
val observer = Observer<T> {
value = it
latch.countDown()
}
latch.await(2, TimeUnit.SECONDS)
observeForever(observer)
removeObserver(observer)
return value
}
Который вы можете назвать так:
val result = viewModel.myLiveData.getTestValue()
Другие проекты делают его частью библиотеки утверждений.
Вот библиотека кто-то написал посвященный тестированию LiveData.
Вы также можете заглянуть в Kotlin Coroutine CodeLab
Или следующие проекты:
https://github.com/googlesamples/android-sunflower
https://github.com/googlesamples/android-architecture-components