我有以下代码:
视图模型:
private val _prefix = MutableStateFlow("")
val prefix: StateFlow<String> = _prefix
private val _firstName = MutableStateFlow("")
val firstName: StateFlow<String> = _firstName
private val _middleName = MutableStateFlow("")
val middleName: StateFlow<String> = _middleName
private val _lastName = MutableStateFlow("")
val lastName: StateFlow<String> = _lastName
private val _suffix = MutableStateFlow("")
val suffix: StateFlow<String> = _suffix
fun saveContact(
prefix: String,
firstName: String,
middleName: String,
lastName: String,
suffix: String,
) {
_prefix.value = prefix
_firstName.value = firstName
_middleName.value = middleName
_lastName.value = lastName
_suffix.value = suffix
}
}
输入与变量相关的所有字段后,我会从我的角度调用
saveContact
。
这是我测试上述工作的方法:
查看测试:
@Test
fun testView_success() {
lateinit var viewModel: ViewModel
ctr.setContent {
viewModel =
ViewModel(AppDatabase.getDatabase(LocalContext.current).dao)
View(
viewModel = viewModel,
buttonActions = ViewButtonActions(
onNavigateBack = {},
onSave = {},
)
)
}
// Let's make sure that we are displaying the correct view.
ctr.onNodeWithTag(tags.testTag).assertIsDisplayed()
/*
* Personal Details
*/
// Let's now show all fields for each section.
ctr.onNodeWithTag(tags.buttonShowHiddenContentPD).performClick()
// Then we'll insert our text.
ctr.onNodeWithTag(tags.textFieldPrefix).performTextInput(TestData.prefix)
ctr.onNodeWithTag(tags.textFieldFirstName).performTextInput(TestData.firstName)
ctr.onNodeWithTag(tags.textFieldMiddleName).performTextInput(TestData.middleName)
ctr.onNodeWithTag(tags.textFieldLastName).performTextInput(TestData.lastName)
ctr.onNodeWithTag(tags.textFieldSuffix).performTextInput(TestData.suffix)
// Then tap the save button again.
ctr.onNodeWithTag(tags.buttonSave)
// Let's now check to see if all of the text has been passed on.
assertEquals(
TestData.prefix, // is "Mr"
viewModel.prefix.value
)
assertEquals(
TestData.firstName, // "Joe"
viewModel.firstName.value
)
assertEquals(
TestData.middleName, // "Ray"
viewModel.middleName.value
)
assertEquals(
TestData.lastName, // "Bloggs
viewModel.lastName.value
)
assertEquals(
TestData.suffix, // "B.sc
viewModel.suffix.value
)
}
但是,当我运行测试时,出现以下错误:
junit.framework.ComparisonFailure: expected:<[Mr]> but was:<[]>
at junit.framework.Assert.assertEquals(Assert.java:85)
at junit.framework.Assert.assertEquals(Assert.java:91)
我将如何测试这样的 MutableStateFlow/StateFlow?看来我的测试没有等待足够长的时间来从 StateFlow 发出正确的数据。
谢谢
您似乎正在尝试同时测试 Composable 和 ViewModel,而您需要为每个组件进行一组不同的测试。
例如,如果您有一个按钮显示“Hello,$name”并将名称保存到您在 UI 更改的仪器测试和单元测试数据库中测试的数据库
因此,
ViewModel
(具有所有业务逻辑)需要进行单元测试。你的相当简单,但测试永远不会有什么坏处:)
@Test
fun testViewModel_success(): Unit {
val viewModel = UnitTestViewModel()
// Assert that everything is set to their initial value
assertEquals(viewModel.prefix.value, "")
assertEquals(viewModel.firstName.value, "")
assertEquals(viewModel.middleName.value, "")
assertEquals(viewModel.lastName.value, "")
assertEquals(viewModel.suffix.value, "")
// call the function to set the values
viewModel.saveContact(TestData.prefix, TestData.first, TestData.middle, TestData.last, TestData.suffix)
// Assert stateFlows have the new values
assertEquals(viewModel.prefix.value, TestData.prefix)
assertEquals(viewModel.firstName.value, TestData.first)
assertEquals(viewModel.middleName.value, TestData.middle)
assertEquals(viewModel.lastName.value, TestData.last)
assertEquals(viewModel.suffix.value, TestData.suffix)
}
现在,对于可组合项,您需要像您拥有的那样进行仪器化测试。仪器测试只是为了检查屏幕上显示的数据是否正确。在您的情况下,如果单击按钮后在 UI 上的某处显示来自
ViewModel
的 StateFlow
的用户数据,您可以通过调用 .assertTextEquals()
或 .assertTextContains()
检查您的 UI 是否正确更新。如果没有,您只能测试 UI 是否适当更改(例如加载指示器、清除 TextField
等)