I've been trying to write unit tests for my Room database, which I've done in the past when I have queries return a list and I create a database that allows main thread queries, but now that I'm trying to test with RxJava values I have no luck.
Here is my DAO code:
@Dao
interface AccountDAO {
@Query("SELECT * FROM account")
fun getAll(): Flowable<List<Account>>
@Insert
fun insert(accounts: List<Account>): List<Long>
//...
}
And here is my database testing code, where I've tried a few things to get it to pass:
@RunWith(AndroidJUnit4::class)
class CCDatabaseTest {
//...
@JvmField @Rule val mainActivity = ActivityTestRule<MainActivity>(MainActivity::class.java)
@Before
fun setUp() {
val context = mainActivity.activity
database = Room.inMemoryDatabaseBuilder(context, CCDatabase::class.java).allowMainThreadQueries().build()
accountDao = database.accountDao()
transactionDao = database.transactionDao()
}
//...
@Test
fun testWriteReadAccount() {
val testAccount = Account(TEST_ACCOUNT_NAME, TEST_ACCOUNT_BALANCE)
val ids = accountDao.insert(listOf(testAccount))
assertEquals(1, ids.size)
val accountsFlowable = accountDao.getAll()
val testSubscriber = TestSubscriber<List<Account>>()
accountsFlowable.subscribe(testSubscriber)
testSubscriber.assertNoErrors()
// Fails: testSubscriber.assertValueCount(1)
// Fails: testSubscriber.assertValue(listOf(testAccount))
// Fails: testSubscriber.assertResult(listOf(testAccount))
}
//...
}
If anyone would actually like to see or test run the code, please check out the app-refresh module of this repository: https://github.com/adammc331/cashcaretaker
DAO: https://github.com/AdamMc331/CashCaretaker/blob/develop/app-refresh/src/main/java/com/adammcneilly/cashcaretaker/daos/AccountDAO.kt
Test class: https://github.com/AdamMc331/CashCaretaker/blob/develop/app-refresh/src/androidTest/java/com/adammcneilly/cashcaretaker/data/CCDatabaseTest.kt
As part of my search to answer this, I commented on a Medium post by Florina Muntenescu and she responded with the answer.
I needed to include the InstantTaskExecutorRule
in my test class. This replaces the background task executor with one that runs everything synchronously. In order to use this, I added the following line to my module's build.gradle file, note that while I had to exclude certain modules (I got a support lib discrepancy between app and test app) you may not:
androidTestCompile ("android.arch.core:core-testing:$roomLibraryVersion") {
exclude module: 'support-compat'
exclude module: 'support-annotations'
exclude module: 'support-core-utils'
}
Now, with that added, my test class looks like this:
@RunWith(AndroidJUnit4::class)
class CCDatabaseTest {
// ...
@JvmField @Rule val instantTaskExecutorRule = InstantTaskExecutorRule()
@JvmField @Rule val mainActivity = ActivityTestRule<MainActivity>(MainActivity::class.java)
@Before
fun setUp() {
val context = mainActivity.activity
database = Room.inMemoryDatabaseBuilder(context, CCDatabase::class.java).allowMainThreadQueries().build()
accountDao = database.accountDao()
}
// ...
@Test
fun testWriteReadAccount() {
val testAccount = Account(TEST_ACCOUNT_NAME, TEST_ACCOUNT_BALANCE)
val ids = accountDao.insert(listOf(testAccount))
assertEquals(1, ids.size)
accountDao.getAll()
.test()
.assertValue(listOf(testAccount))
}
// ...
}
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