【问题标题】:Android: How to set private MutableLiveData in unit testAndroid:如何在单元测试中设置私有的 MutableLiveData
【发布时间】:2021-01-03 05:19:35
【问题描述】:

我正在尝试通过编写一些单元测试来测试我的viewmodel。我的问题是,如果不为 MutableLiveData 手动设置一些值(在生产中它们是通过数据绑定设置的),我就无法实现我的目标。这里的问题是我的 MutableLiveData (显然)是private,因此我无法通过在单元测试中写入mutablelivedata.value = "Some Value" 来设置值。

我读过一些文章,有人说我应该通过编写自定义设置器来公开我的 MutableLiveData:

private val _myMutableLiveData = MutableLiveData<String>()
val myPublicLiveData: LiveData<String> get() = _myMutableLiveData

// setter
fun setStringForLiveData(value: String) {
   _myMutableLiveData.value = value
}

我的问题来了:将 MutableLiveData 设置为 private 但使用自定义 setStringForLiveData(value: String) 公开 setter 和使用 myPublicLiveData 公开 getter 有什么意义。我的意思是,当我同时公开 private 字段的 getter 和 setter 时,为什么我不应该将其公开?

这是我目前测试 MutableLiveData 的方法(我不知道这是否有意义甚至是否有效)

@Test
fun `first shipping text should be set correctly`() {
   (viewModel.secondDropDownVisibility as MutableLiveData<Boolean>).value = false
   (viewModel.shippingFirstDdText as MutableLiveData<String>).value = "Toast"
    assertEquals("Toast", viewModel.decideShippingTextOne())
}

我希望有比为每个 mutablelivedata 编写自定义设置器更好的方法(我有 20 多个,这只是丑陋的样板代码)。也许我在这里误解了一些东西。

请记住,我对 Android 开发和 MVVM 概念,尤其是 Livedata 还比较陌生。

感谢每一个帮助,谢谢!

【问题讨论】:

    标签: android kotlin mvvm android-livedata android-mvvm


    【解决方案1】:
    private val _myMutableLiveData = MutableLiveData<String>()
    val myPublicLiveData: LiveData<String> get() = _myMutableLiveData
    
    // setter
    fun setStringForLiveData(value: String) {
       _myMutableLiveData.value = value
    }
    

    抱歉,这段代码没有意义。如果您绝对需要这样做,则无需使用双字段,因为无论如何您都在公开可变状态。

    话虽如此,我认为您需要诉诸于此,这通常是一种代码味道。我看不到你的整个视图模型,但我假设你有一个公共函数(或一些初始化代码)触发一些工作并将数据推送到实时数据,这就是你必须测试的。如果您想上传您的完整视图模型,我可以尝试通过更新答案来建议测试方法。干杯!

    【讨论】:

    • 我会尝试重新考虑我的方法,也许我什至不需要测试这些“我的视图模型中的特定函数”,因为它们只是使用我已经测试过的模型中的其他公共函数。我不认为我可以发布整个 Viewmodel,因为它有超过 400 行代码(负责包含 3 个片段和大量编辑文本的导航图)
    【解决方案2】:

    好的,这可能不是最好的答案,但这对我有用。在这一点上,我并不真正关心“哦,不,但这在 android 编程中是不对的”或“但你不应该在单元测试中那样做”。测试用例有效,这就是我所需要的。

    @Test
    fun `first shipping text should be set correctly`() {
       (viewModel.secondDropDownVisibility as MutableLiveData<Boolean>).value = false
       (viewModel.shippingFirstDdText as MutableLiveData<String>).value = "Toast"
        assertEquals("Toast", viewModel.decideShippingTextOne())
    }
    

    我有两个_secondDropDownVisibility_shippingFirstDdText 类型的MutableLiveData&lt;T&gt; 私有字段和两个secondDropDownVisibilityshippingFirstDdText 类型LiveData&lt;T&gt; 的公共字段

    干杯

    【讨论】:

      【解决方案3】:

      如果您需要从外部修改 MutableLiveData(不对方法做出任何额外保证),您应该按原样公开 MutableLiveData。

      如果您一直在使用数据绑定,那么您将暴露 ObservableField,它也是可读/可写的。

      【讨论】:

      • 但我只需要在我的 TESTS 中修改 MutableLiveData 即可,其他任何地方都不需要。我非常怀疑这是推荐的方式。为什么我要公开一些通常只是为了测试而私有的东西?那太可怕了。不,我没有使用 observableField 进行数据绑定(没有人应该这样做),我使用的是正常的生命周期感知 lifedata。
      • 仅出于测试目的而公开字段通常是代码异味,这意味着您在设计时没有考虑到测试
      • 如果你不能从外部访问它,那么不要从测试中访问它??‍♀️
      猜你喜欢
      • 2017-07-23
      • 1970-01-01
      • 1970-01-01
      • 2014-03-02
      • 1970-01-01
      • 1970-01-01
      • 2011-01-29
      • 2012-01-02
      • 2019-05-16
      相关资源
      最近更新 更多