I am writing an app that has a form where the user enters data:
Column {
TextField(
label = { Text(text = stringResource(id = R.string.brand)) },
value = state.value.brand,
onValueChange = { state.value = state.value.copy(brand = it) }
)
// ... and more
}
When the user taps the save button, I use Room API to save the data to a local SQLite database:
fun saveCard(db: BaseballCardDatabase, cardState: BaseballCardState) {
val newCard = cardState.toBaseballCard()
runBlocking {
launch {
db.baseballCardDao.insertBaseballCard(newCard)
}
}
}
Now I want to write a test for this form. I can successfully automate entering data into the form and clicking the save button:
composeTestRule
.onNodeWithText("Brand")
.assertIsDisplayed()
.performTextInput(card.brand)
// ... etc
composeTestRule
.onNodeWithContentDescription("Save")
.performClick()
Now I want to verify that a new row was inserted in the database. How do I query the database from a test?
My attempt was like this:
val context = InstrumentationRegistry.getInstrumentation().targetContext
val db = inMemoryDatabaseBuilder(context, BaseballCardDatabase::class.java).build()
runBlocking {
launch {
val savedCard = db.baseballCardDao.getBaseballCards().single()
assert(savedCard == card)
}
}
But this just hangs forever. I assume it is because of the runBlocking
context, but not entirely sure. How do I do this correctly?
try it:
CoroutineScope(Dispatchers.IO).launch {
val savedCard = db.baseballCardDao.getBaseballCards().single()
assert(savedCard == card)
}
when you use runBlocking
. it will block the main thread. if you use runblocking
. it should crash the app not hangs.
Also this is just a way for you to test. In fact you should create a coroutine object to be able to use it like this.
val coroutineScope = CoroutineScope(Dispatchers.IO)
coroutineScope.launch {
val savedCard = db.baseballCardDao.getBaseballCards().single()
assert(savedCard == card)
}
or use the viewModelScope
object in ViewModel
(if you use ViewModel)