I'm testing with AS 3.4.1 and Emulator running Android 9.
The following test won't run, when I use a Room Dao Function annotated with @Transaction
in it.
class RecurrenceManagerTest : DatabaseTest() {
@Rule
@JvmField
val instantTaskExecutorRule = InstantTaskExecutorRule()
var recurringEntryId: Long = -1
@Before
override fun setup() {
super.setup() // only initialized the db
val recurringEntry = RecurringEntry(
recurrence = Recurrence(DATE.toEpochMilli(), Recurrence.DAILY)
)
recurringEntryId = runBlocking { db.recurringEntryDao().insert(recurringEntry) }
val recurringBookEntry = BookEntry.create(
title = TITLE,
date = DATE,
value = VALUE,
isPaid = IS_PAID,
notes = NOTES,
entryType = ENTRY_TYPE,
categoryId = CATEGORY_ID,
contacts = CONTACTS,
recurringEntryId = recurringEntryId
)
runBlocking {
db.bookEntryDao().insert(recurringBookEntry) // BreakPoint #1
}
}
@Test
fun testInsertRecurrencesAndSchedule() {
var recurringEntry = runBlocking { db.recurringEntryDao().get(recurringEntryId) } // BreakPoint #2
assertThat(recurringEntry, notNullValue())
runBlocking { RecurrenceManager.insertRecurrencesAndSchedule(ApplicationProvider.getApplicationContext(), db, recurringEntry!!) }
val bookEntries = db.bookEntryDao().getBookEntries().liveDataValue()
}
}
This is the function for inserting:
@Transaction
suspend fun insert(bookEntry: BookEntry): Long {
val id = insert(bookEntry.entity)
bookEntry.embeddedContacts?.apply {
forEach {
it.id = 0
it.bookEntryId = id
}
}?.let {
insert(it)
}
return id
}
So if I'm running the test like it is (see BreakPoint #1), BreakPoint #2 won't even be called, so the test ends somewhere before, without a result.
If I'm replacing the code at BreakPoint #1 with exact the same code, the insert
function has, the test runs correctly.
Does anyone have an idea what's the issue here?
You can use setTransactionExecutor to run transaction in another thread
return Room
.inMemoryDatabaseBuilder(context, MyRoomDatabase::class.java)
.setTransactionExecutor(Executors.newSingleThreadExecutor())
.build()
then while testing use runBlocking instead of runBlockingTest
@Test
fun moveItem() = runBlocking {
transactionFunction()
}
I faced the same issue and the problem was because of the InstantTaskExecutorRule
, if you remove the below block of code the @Transaction
should work fine with the suspend
keyword
@Rule
@JvmField
val instantTaskExecutorRule = InstantTaskExecutorRule()
It seems that this rule blocks the RoomDatabase
from acquiring the transaction thread. In RoomDatabase.kt
execution gets blocked in the below function:
private suspend fun Executor.acquireTransactionThread(controlJob: Job): ContinuationInterceptor
Hope this helps!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With