Ao realizar um teste utilizando coroutine
me deparei com esse problema ao tentar observar um LiveData
Cannot invoke observeForever on a background thread
Para contextualizar o problema, eu estava utilizando um dao
do Room
com uma suspend
function para me retornar um LiveData
, exemplo:
@Test
fun myTest() = runBlocking {
val liveData = dao.selectAll()
val value = getValue(liveData)
//asserts
}
/**
* Helper method for testing LiveData objects, from
* https://github.com/googlesamples/android-architecture-components.
*
* Get the value from a LiveData object. We're waiting for LiveData to emit, for 2 seconds.
* Once we got a notification via onChanged, we stop observing.
*/
@Throws(InterruptedException::class)
fun <T> getValue(liveData: LiveData<T>): T {
val data = arrayOfNulls<Any>(1)
val latch = CountDownLatch(1)
liveData.observeForever { o ->
data[0] = o
latch.countDown()
}
latch.await(2, TimeUnit.SECONDS)
@Suppress("UNCHECKED_CAST")
return data[0] as T
}
O problema é a execução do observer
fora da thread
da interface, para solucionar esse problema nos seus testes temos que adicionar ao AndroidJUnit4
uma Rule
, para fazer isso basta adicionar a seguinte váriavel na sua classe de teste:
@get:Rule
var instantTaskExecutorRule = InstantTaskExecutorRule()
Você precisa adicionar a seguinte dependência para instanciar um InstantTaskExecutorRule
androidTestImplementation "androidx.arch.core:core-testing:2.0.0"
Essa solução foi encontrada no projeto Sunflower
de exemplo da nova arquitetura do android, segue o link do arquivo:
https://github.com/android/sunflower/blob/master/app/src/androidTest/java/com/google/samples/apps/sunflower/data/GardenPlantingDaoTest.kt