Testing Android Room with LiveData, Coroutines and Transactions

前端 未结 2 1233

I want to test my database layer and I have caught myself in a catch-22 type of a situation.

The test case consists of two things:

  • Save so
相关标签:
2条回答
  • 2021-02-19 11:40

    The problem is with the thing that transactions itself use runBlocking somewhere inside and that cause deadlock. I have changed InstantTaskExecutorRule to this class:

    class IsMainExecutorRule : TestWatcher() {
    
        val defaultExecutor = DefaultTaskExecutor()
    
        override fun starting(description: Description?) {
            super.starting(description)
            ArchTaskExecutor.getInstance().setDelegate(object : TaskExecutor() {
                override fun executeOnDiskIO(runnable: Runnable) {
                    defaultExecutor.executeOnDiskIO(runnable)
                }
    
                override fun postToMainThread(runnable: Runnable) {
                    defaultExecutor.executeOnDiskIO(runnable)
                }
    
                override fun isMainThread(): Boolean {
                    return true
                }
            })
        }
    
        override fun finished(description: Description?) {
            super.finished(description)
            ArchTaskExecutor.getInstance().setDelegate(null)
        }
    }
    

    Then in code it will be:

    @get:Rule
    val liveDataRule = IsMainExecutorRule()
    

    It will not cause deadlocks but still allow to observe livedatas.

    0 讨论(0)
  • 2021-02-19 12:04

    There is now a solution to this issue, explained in this answer.

    The fix is adding a single line to the Room in-memory database builder:

    db = Room
        .inMemoryDatabaseBuilder(context, AppDatabase::class.java)
        .setTransactionExecutor(Executors.newSingleThreadExecutor()) // <-- this makes all the difference
        .build()
    

    With the single thread executor the tests are working as expected.

    0 讨论(0)
提交回复
热议问题