如何断言 next started activity 用于可组合测试?

How to assert next started activity for a composable test?

我有一个带有按钮的可组合项,可以启动其中一个本机活动(Google 设置)。 要在撰写之前对此进行测试(使用 Robolectric),我会做这样的事情:

我的测试:

@Test
fun `MyFragment - when button clicked - starts activity`() {
    // ...
    val shadowActivity: ShadowActivity = Shadow.extract(activity)
    val nextStartedActivity = shadowActivity.nextStartedActivity
    assertNotNull(nextStartedActivity)
    assertEquals(Settings.ACTION_APPLICATION_DETAILS_SETTINGS, nextStartedActivity.action)
}

使用组合测试(不使用 activity 场景)是不同的。没有 activity 句柄,只有 composeTestRule:

我的测试:

// ...

private val buttonNode get() = composeTestRule.onNodeWithContentDescription("Button")

@Test
fun `MyComposableToTest - when button clicked - starts activity`() {
    composeTestRule.setContent {
        MyComposableToTest()
    }

    buttonNode.assertExists().assertHasClickAction().assertIsEnabled().performClick()

    // No possibility to get current activity
}

如何断言在测试可组合项时启动了一个新的 activity?

一些上下文:

您可以像这样从 ComposeContentTestRule 获取上下文:

lateinit var context : Context
composeTestRule.setContent {
    context = LocalContext.current
    MyComposableToTest()
}

然后断言下一个开始activity

val shadowActivity: ShadowActivity = Shadow.extract(context as ComponentActivity)
val nextStartedActivity = shadowActivity.nextStartedActivity
assertEquals(Settings.ACTION_APPLICATION_DETAILS_SETTINGS, nextStartedActivity.action)

这就是我为仪器测试所做的(不使用 Robolectric)。

build.gradle[.kts]:

androidTestImplementation("androidx.test.espresso:espresso-intents:3.4.0")

测试class(在src/androidTest/...目录下):

import androidx.test.espresso.intent.Intents
import androidx.test.espresso.intent.Intents.intended
import androidx.test.espresso.intent.matcher.IntentMatchers.hasComponent
// ...

@RunWith(AndroidJUnit4::class)
class MainActivityInstrumentedTest {
    @get:Rule val composeTestRule = createAndroidComposeRule<MainActivity>()

    @Test fun testTheIntent() {
        Intents.init() // IMPORTANT (to be able to use "intended" function)
        composeTestRule.setContent {
            MyAppTheme {
                MainScreen()
            }
        }
        composeTestRule.onNodeWithText("My Button").performClick()
        intended(hasComponent(MySecondActivity::class.java.name))
        Intents.release()
    }
}