espresso 测试“无法访问主线程上的数据库”时出现房间数据库错误

Posted

技术标签:

【中文标题】espresso 测试“无法访问主线程上的数据库”时出现房间数据库错误【英文标题】:Room Database Error when espresso test "Cannot access database on the main thread" 【发布时间】:2022-01-01 20:43:01 【问题描述】:

我正在使用 espresso 进行测试,但在执行以下方法时出现错误。

viewModel.getData().observe(viewLifecycleOwner, Observer  options ->
            Log.d(TAG, "onViewCreated: $options")
            val data = options.filter  option -> option.type!! == OptionType.DATA

            updateData.updateUIComponent(data)
        )

get data 方法返回一个 LiveData 对象。这在 Fragments 中运行良好,但在 espresso 测试类中不起作用

Cannot access database on the main thread since it may potentially lock the UI for a long period of time.

这是我的测试课

@LargeTest
@RunWith(androidJUnit4::class)
open class BaseIntegrationTest 

    @get:Rule
    val instantTestExecutorRule = InstantTaskExecutorRule()

    lateinit var navController: TestNavHostController

    lateinit var fragmentScenario: FragmentScenario<DetailsFragment>


    @Before
    fun initTest() 

        navController = TestNavHostController(
            ApplicationProvider.getApplicationContext()
        )

    

    @Test
    fun launchFragment() 

        val bundle = Bundle()

        fragmentScenario =
            launchFragmentInContainer(bundle, themeResId = R.style.Theme_mainTheme)

        fragmentScenario.moveToState(Lifecycle.State.STARTED)

        UiThreadStatement.runOnUiThread 
            navController.setGraph(R.navigation.app_navigation_graph)
        
        fragmentScenario.onFragment  fragment ->

            //CollectFeedbackFragment()
            Navigation.setViewNavController(fragment.requireView(), navController)
        

        onView(withId(R.id.progressBar)).isVisible()
    


【问题讨论】:

liveData 的回调未在 prod 的主线程上运行,但测试(您尚未显示)通常使用InstantTaskExecutorRule 或类似的将后台执行程序交换为同步执行程序(显示你的测试?)。您需要修改您的数据库(在您的测试中)以允许在主线程上进行查询,或者使用runBlocking 变体来等待。 @MartinMarconcini 我已经使用了 InstantTaskExecutorRule,但它对我不起作用。我想知道普通的 Fragments 和单元测试类都在 UI 线程中运行,但在 Fragments 中运行良好,但在测试类中它的行为不同 【参考方案1】:

我设法通过使用 Dispatchers.IO 和 Dispatchers.Main 解决了这个问题

class SampleViewModel : ViewModel() 

    fun getData():DataLiveData 
        viewModelScope.launch 

            withContext(Dispatchers.IO) 

                 // here I am seding the Room db call
                
                withContext(Dispatchers.Main) 
               // I am updating the MutableLiveData object here
                
            
        
        return mutableLiveData
    
   

并且不要忘记注入调度程序而不是硬编码。 点击here!

【讨论】:

以上是关于espresso 测试“无法访问主线程上的数据库”时出现房间数据库错误的主要内容,如果未能解决你的问题,请参考以下文章

“无法访问主线程上的数据库,因为它可能会长时间锁定 UI。”我的协程错误

Espresso:如何测试 SwipeRefreshLayout?

Android Studio 2.2 Espresso Test Recorder-----解放双手,通过录制测试过程实现测试

在 Espresso 测试中忽略 pressBack()

Android 自动化测试 Espresso篇:异步代码测试

AsyncTask 运行时 Espresso 测试返回按钮