【发布时间】: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<MainActivity>()中调用的 MainActivity 并注释掉 setContent 块,测试就会正常运行。所以只能有一个setContent。因此,要么我应该设置一个虚拟的、空的 MainActivity 用于测试目的,要么编写一个不设置自己的内容但导航到要测试的屏幕的测试?
标签: android android-jetpack-compose android-jetpack-compose-material3