【问题标题】:How to perform Android tests with Compose and Material3?如何使用 Compose 和 Material3 执行 Android 测试?
【发布时间】:2022-10-06 23:01:12
【问题描述】:

曾经正常执行的相当标准的 Android 测试现在无法构建,因为我已将基于 Jetpack Compose 的应用程序升级到 Material3。

他们在构建时都给了我同样的错误:

java.lang.IllegalStateException: blahblah.ui.MainActivity@b265e73 has already set content. If you have populated the Activity with a ComposeView, make sure to call setContent on that ComposeView instead of on the test rule; and make sure that that call to `setContent {}` is done after the ComposeTestRule has run

错误由以下人员引发:

at androidx.compose.ui.test.AndroidComposeUiTestEnvironment$AndroidComposeUiTestImpl.setContent(ComposeUiTest.android.kt:452)`
at androidx.compose.ui.test.junit4.AndroidComposeTestRule.setContent(AndroidComposeTestRule.android.kt:200)
at blahblah.feature_memo_gallery.presentation.memo_gallery.MemoGalleryScreenTest.setUp(MemoGalleryScreenTest.kt:45)

这是一个测试示例,它曾经可以正常构建和运行,但不再构建。

import androidx.compose.animation.ExperimentalAnimationApi
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.SnackbarHostState
import androidx.compose.runtime.remember
import androidx.compose.ui.test.assertIsDisplayed
import androidx.compose.ui.test.junit4.createAndroidComposeRule
import androidx.compose.ui.test.onNodeWithContentDescription
import androidx.compose.ui.test.onNodeWithTag
import androidx.compose.ui.test.performClick
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.rememberNavController
import blahblah.core.di.AppModule
import blahblah.feature_memo_gallery.presentation.memo.MemoScreen
import blahblah.ui.MainActivity
import blahblah.ui.navigation.Screen
import blahblah.ui.theme.ScriblettTheme
import dagger.hilt.android.testing.HiltAndroidRule
import dagger.hilt.android.testing.HiltAndroidTest
import dagger.hilt.android.testing.UninstallModules
import org.junit.Before
import org.junit.Rule
import org.junit.Test

@HiltAndroidTest
@UninstallModules(AppModule::class)
class MemoGalleryScreenTest {

    @get:Rule(order = 0)
    val hiltRule = HiltAndroidRule(this)

    @OptIn(ExperimentalMaterial3Api::class)
    @get:Rule(order = 1)
    val composeRule = createAndroidComposeRule<MainActivity>()

    @OptIn(ExperimentalMaterial3Api::class)
    @ExperimentalAnimationApi
    @Before
    fun setUp() {
        hiltRule.inject()
        composeRule.setContent {  <<<<========= THIS LINE THROWS THE ERROR
            val navController = rememberNavController()
            val snackbarHostState = remember { SnackbarHostState() }
            ScriblettTheme {
                NavHost(
                    navController = navController,
                    startDestination = Screen.MemoScreen.route
                ) {
                    composable(route = Screen.MemoScreen.route) {
                        MemoScreen(navController = navController, snackbarHostState)
                    }
                }
            }
        }
    }

    @OptIn(ExperimentalMaterial3Api::class)
    @Test
    fun clickSortButton_sortIsVisible() {
        composeRule.onNodeWithTag(TestTags.SORT).assertDoesNotExist()
        composeRule.onNodeWithContentDescription(\"Sort\").performClick()
        composeRule.onNodeWithTag(TestTags.SORT).assertIsDisplayed()
    }
}

我的问题是,我不太明白错误信息。我怀疑它与 Material3 相关,因为它是我改变导致错误的东西,但我并没有真正有雾。

  • 我发现如果我转到 val composeRule = createAndroidComposeRule&lt;MainActivity&gt;() 中调用的 MainActivity 并注释掉 setContent 块,测试就会正常运行。所以只能有一个setContent。因此,要么我应该设置一个虚拟的、空的 MainActivity 用于测试目的,要么编写一个不设置自己的内容但导航到要测试的屏幕的测试?

标签: android android-jetpack-compose android-jetpack-compose-material3


【解决方案1】:

您应该使用val composeRule = createComposeRule(),然后在此使用'setContent()'。这将创建一个空/shell 活动来设置您的内容。确保将debugImplementation("androidx.compose.ui:ui-test-manifest:version") 添加到 gradle。

【讨论】:

    猜你喜欢
    • 2022-08-09
    • 2022-11-06
    • 2022-11-06
    • 2022-08-17
    • 2020-06-11
    • 2023-02-12
    • 2022-11-06
    • 2021-07-26
    • 1970-01-01
    相关资源
    最近更新 更多