Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Test RxJava2 Flowable Query Room

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

like image 377
AdamMc331 Avatar asked Aug 26 '17 15:08

AdamMc331


1 Answers

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))
    }

    // ...
}
like image 171
AdamMc331 Avatar answered Nov 02 '22 20:11

AdamMc331