Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Roboelectric with Room Database for android

How to do unit testing of Room Database with the help of Roboeletric?

I don't want to do instrumentation testing.

like image 732
Dinjit Avatar asked Jan 23 '19 12:01

Dinjit


2 Answers

From what I can tell it can be done like this

//@RunWith(AndroidJUnit4::class)
@RunWith(RobolectricTestRunner::class)
class WordDaoTest {
    private lateinit var wordRoomDatabase: WordRoomDatabase
    private lateinit var wordDao: WordDao

    @get:Rule
    var instantTaskExecutor = InstantTaskExecutorRule()

    @Before
    fun createDb() {
        val context = InstrumentationRegistry.getInstrumentation().targetContext
        wordRoomDatabase = Room.inMemoryDatabaseBuilder(context, WordRoomDatabase::class.java).allowMainThreadQueries().build()
        wordDao = wordRoomDatabase.wordDao()

        wordRoomDatabase.wordDao().insertAll(listOf<Word(Word("one"),Word("two"),Word("three"))
    }

    @After
    fun closeDb() {
        wordRoomDatabase.close()
    }

    @Test
    fun testGetName() {
        Assert.assertThat(getValue(wordDao.getAllLiveWords()).size, equalTo(3))
    }
}

It seems though you need allowMainThreadQueries() in the build of the DB.

I am not sure as to why everyone tests the Dao in the instrumentation test when it can be done in the Unit Test and then be added to code coverage (maybe someone else has some insight)

This code is in Kotlin but I am sure it would translate to java just the same.

This was provided to me however as to why it's not considered to be best practice https://developer.android.com/training/data-storage/room/testing-db

Note: Even though this setup allows your tests to run very quickly, it isn't recommended because the version of SQLite running on your device—and your users' devices—might not match the version on your host machine.

like image 198
Crash1hd Avatar answered Oct 01 '22 15:10

Crash1hd


Robolectric can support such JVM unit tests with Room.

To get the required context, please add below dependency in your build.gradle:

testImplementation 'androidx.test:core:1.2.0'

Let's assume that we have a repository class which wraps the Room Dao. And here's a quick example:

@RunWith(RobolectricTestRunner::class)
@Config(sdk = [28]) // This config setting is the key to make things work
class FooRepositoryTest {

    @get:Rule
    var instantTask = InstantTaskExecutorRule()

    private lateinit var database: MyDatabase

    private lateinit var sut: FooRepository

    @Before
    fun setUp() {
        val context = ApplicationProvider.getApplicationContext<Context>()
        database = Room.inMemoryDatabaseBuilder(context, MyDatabase::class.java)
            .allowMainThreadQueries()
            .build()
        sut = FooRepository(database.fooDao())
    }

    @After
    fun tearDown() {
        database.close()
    }
}
like image 29
jxsun Avatar answered Oct 01 '22 14:10

jxsun