Android Navigation Instrumentation 测试抛出必须在主线程上调用方法 addObserver

问题描述 投票:0回答:6

我有两个片段,其中一个是我图中的主片段。单击按钮后,用户将导航到第二个片段。它按预期工作,将用户导航到第二个片段并显示文本。所以图表很好。

现在我想编写一个仪器测试。

@RunWith(AndroidJUnit4::class)
class TransitionTest {

    @Test
    fun testNavigationToSecondFragment() {
        
        val navController = TestNavHostController(
            ApplicationProvider.getApplicationContext())

        navController.setGraph(R.navigation.my_graph) <--throws exception

        // the rest of my test continues here
    }
}

但是,上面显示的用于设置图表的行会引发以下异常:

IllegalStateException:必须在 main 上调用方法 addObserver 线程。

我的环境:

fragment_version = 1.2.5 nav_version = 2.3.1 espresso = 3.3.0

有人知道发生了什么事以及如何解决吗?

kotlin android-espresso android-navigation-graph
6个回答
20
投票

我将

setGraph
函数包装在
runOnUiThread
中,测试通过了。一旦找到真正的原因和更好的解决方案,我会更新答案。

runOnUiThread {
    navController.setGraph(R.navigation.my_graph)
}

12
投票

我也遇到了同样的问题,所以我会尝试解释其根本原因。 从

androidx.lifecycle:lifecycle-*:2.3.0-alpha06
开始。
LifecycleRegistry 
的行为发生了变化。
LifecycleRegistry
现在验证其方法是否在主线程上调用。现在还有另一个未解决的问题:仪器测试是否在主线程中运行?显然没有,否则它就会过去。它使用 Instrumentation Thread 来运行大多数测试。根据文档,您可以使用
@UiThreadTest
runOnUiThread
,如顶部的 answer


4
投票

升级软件包后我也开始遇到这个问题:

implementation 'androidx.activity:activity:1.2.0-alpha06'

 implementation 'androidx.activity:activity:1.2.0-beta01'

在我的代码中,我在后台线程中打开一个片段,这似乎与新包有关。片段在生命周期中添加观察者:

我认为将调用包装在 UI 线程上运行的解决方法是唯一合理的解决方案,因为观察者也可能在您的情况下在内部添加。


4
投票

还有另一种解决方案可以使用此解决方案

InstrumentationRegistry.getInstrumentation().runOnMainSync {
            navController.setGraph(R.navigation.my_graph)
        }

由于

@UiThreadTest
仅适用于
@Test
@Before
@After
,因此如果您有一些常见的测试功能,它们可能无法按预期工作


0
投票

当我的 com.google.gms:google-services 库与 appcompat 版本冲突时,我遇到了这个问题。当我将 appcompat 版本更改为以下版本时,问题得到解决

implementation 'androidx.appcompat:appcompat:1.3.0'

0
投票

当我尝试从 ViewModel (视图模型类)导航到其他屏幕时,我遇到了同样的问题。当我使用 viewModelScope.launch 进行导航时,问题得到了解决

例如。

viewModelScope.launch { 
    navController.navigate(Route.LOGIN_SCREEN) 
}
© www.soinside.com 2019 - 2024. All rights reserved.