Android instrumented test freezes when it tests a suspend function that uses RoomDatabase.withTransaction

大兔子大兔子 提交于 2021-01-05 06:16:17

问题


I'm trying to test the following LocalDataSource function, NameLocalData.methodThatFreezes function, but it freezes. How can I solve this? Or How can I test it in another way?

Class to be tested

class NameLocalData(private val roomDatabase: RoomDatabase) : NameLocalDataSource {

  override suspend fun methodThatFreezes(someParameter: Something): Something {
    roomDatabase.withTransaction {
      try {
        // calling room DAO methods here
      } catch(e: SQLiteConstraintException) {
        // ...
      }
      return something
    }
  }
}

Test class

@MediumTest
@RunWith(AndroidJUnit4::class)
class NameLocalDataTest {
  private lateinit var nameLocalData: NameLocalData

  // creates a Room database in memory
  @get:Rule
  var roomDatabaseRule = RoomDatabaseRule()

  @get:Rule
  var instantTaskExecutorRule = InstantTaskExecutorRule()

  @Before
  fun setup() = runBlockingTest {
     initializesSomeData()
     nameLocalData = NameLocalData(roomDatabaseRule.db)
  }

 @Test
 fun methodThatFreezes() = runBlockingTest {
    nameLocalData.methodThatFreezes // test freezes
 }

 // ... others NameLocalDataTest tests where those functions been tested does not use
 // roomDatabase.withTransaction { } 
}

Gradle's files configuration

espresso_version = '3.2.0'
kotlin_coroutines_version = '1.3.3'
room_version = '2.2.5'

test_arch_core_testing = '2.1.0'
test_ext_junit_version = '1.1.1'
test_roboletric = '4.3.1'
test_runner_version = '1.2.0'

androidTestImplementation "androidx.arch.core:core-testing:$test_arch_core_testing"
androidTestImplementation "androidx.test.espresso:espresso-core:$espresso_version"
androidTestImplementation "androidx.test.ext:junit:$test_ext_junit_version"
androidTestImplementation "androidx.test:rules:$test_runner_version"
androidTestImplementation "androidx.test:runner:$test_runner_version"
androidTestImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:$kotlin_coroutines_version"

回答1:


Last time I wrote a test for Room database I just simply use runBlock and it worked for me... Could you take a look into this sample and check if it works for you as well?

Edit: Ops! I missed this part... I tried this (in the same sample):

  1. I defined a dummy function in my DAO using @Transaction
@Transaction
suspend fun quickInsert(book: Book) {
    save(book)
    delete(book)
}
  1. I think this is the key of the problem. Add setTransactionExecutor to your Database instantiation.
appDatabase = Room.inMemoryDatabaseBuilder(
    InstrumentationRegistry.getInstrumentation().context,
    AppDatabase::class.java
).setTransactionExecutor(Executors.newSingleThreadExecutor())
    .build()
  1. Finally, the test worked using runBlocking
@Test
fun dummyTest() = runBlocking {
    val dao = appDatabase.bookDao();
    val id = dummyBook.id

    dao.quickInsert(dummyBook)

    val book = dao.bookById(id).first()
    assertNull(book)
}

See this question.



来源:https://stackoverflow.com/questions/61648948/android-instrumented-test-freezes-when-it-tests-a-suspend-function-that-uses-roo

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!