使用Room数据库的Roboelectric for Android

9
如何借助Roboeletric进行Room数据库的单元测试?
我不想进行仪器测试。
2个回答

15

根据我的了解,可以像这样完成

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

似乎需要在数据库的构建中允许allowMainThreadQueries()。

我不确定为什么每个人都在仪器测试中测试Dao,而可以在单元测试中完成,然后添加到代码覆盖范围内(也许有其他人有一些见解)。

这段代码是用Kotlin编写的,但我确定它可以同样地转换成Java。

这是提供给我的内容,但为什么它不被认为是最佳实践,原因如下: https://developer.android.com/training/data-storage/room/testing-db

注意:即使此设置使您的测试非常快速运行,也不建议使用,因为运行在设备上和用户设备上的SQLite版本可能与主机机器上的版本不匹配。


5
“might not match the version on your host machine”可能不会与您的主机上的版本匹配。这是我认为不加速测试的最奇怪的理由。就像有数不清的Android设备正在运行不同版本的操作系统一样。什么让任何人觉得在单个设备/模拟器上勉强缓慢测试代码比在主机上运行更好呢? - Srg
我无法在测试实现中获取InstrumentationRegistry.getInstrumentation().targetContext,我的意思是不是仪器。有任何原因吗? - Irfan Ul Haq

3

Robolectric可以支持与Room一起进行此类JVM单元测试。

要获取所需的上下文,请在您的build.gradle中添加以下依赖项:

testImplementation 'androidx.test:core:1.2.0'

假设我们有一个仓库类,它包装了Room Dao。以下是一个快速示例:

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接