在 Android Compose 中测试 MutableStateFlow?

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

我有以下代码:

视图模型:

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 发出正确的数据。

谢谢

kotlin android-jetpack-compose android-testing kotlin-stateflow
1个回答
0
投票

您似乎正在尝试同时测试 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
等)

© www.soinside.com 2019 - 2024. All rights reserved.