【问题标题】:ObservableField value changes not propagatedObservableField 值更改未传播
【发布时间】:2018-04-18 16:44:10
【问题描述】:

我是 mvvm 和 rxbinding 的新手。 我正在尝试使用 RxJava 和 DataBinding 将我的 ViewModel 与 android 上下文完全分离。

当我对 ViewModel 的某些代码进行单元测试(即表单验证)时,我的 ObservableFields 不会更改值并且该值保持为空。

我的 ViewModel 的最小示例:

class RegistrationViewModel(var validator: Validator) : ViewModel {

    val username: ObservableField<String> = ObservableField()
    val password: ObservableField<String> = ObservableField()

    var signInButtonEnabled: ObservableField<Boolean>
    var emailErrorVisibility: ObservableField<Boolean>

    private fun validatePassword(password: String?) = password?.trim()!!.length >= 6

    private fun validateUsername(username: String?) = validator.isValid(Validator.Field.EMAIL, username)

    init {
        val inputValid = Observable.combineLatest(
                toObservable(username),
                toObservable(password),
                BiFunction<String, String, Boolean> { t1, t2 ->
                    validateUsername(t1) && validatePassword(t2)
                }
        )

        signInButtonEnabled = toField(inputValid)
        emailErrorVisibility = toField(toObservable(username).map { t -> !validateUsername(t) })
    }
}

我希望 ObservableField 的 emailErrorVisibility 会在 ObservableField 用户名的值发生变化时设置

我的单元测试:

@Test
fun test_hideUsernameErrorMessage() {
        val validator = mock(RegistrationValidator::class.java)

        val viewModel = RegistrationViewModel(validator)

        viewModel.username.set("")
        assertThat(viewModel.emailErrorVisibility.get(), equalTo(false))

        val invalidValue = "ABC"
        Mockito.`when`(validator.isValid(Validator.Field.EMAIL, invalidValue)).thenReturn(false)
        viewModel.username.set(invalidValue)
        assertThat(viewModel.username.get(), equalTo(invalidValue))
        assertThat(viewModel.emailErrorVisibility.get(), equalTo(true))
}

在此测试中,在viewModel.username.set("") 行之后,viewMode.emailErrorVisibility 的值仍然不是。

值应该通过更改/设置用户名值来更新自己,我错了吗?

注意,toField(Observble) 函数来自https://github.com/manas-chaudhari/android-mvvm/blob/master/android-mvvm/src/main/java/com/manaschaudhari/android_mvvm/FieldUtils.java

【问题讨论】:

  • 我刚刚发现,只有在单元测试中调用 .set 方法时它才起作用。当它通过数据绑定完成时,它就像一个魅力。
  • 刚刚更新了示例

标签: android mvvm kotlin rx-java android-databinding


【解决方案1】:

数据绑定在设置绑定值时尝试高效。更改值时,它会发布以确保您在设置所有值之前完成更改。如果您仍在进行更改,则无需评估更改。

您可以使用executePendingBindings() 强制评估此类情况下的绑定值:

    viewModel.username.set("")
    binding.executePendingBindings()
    assertThat(viewModel.emailErrorVisibility.get(), equalTo(false))

【讨论】:

  • 我认为您的意思是 executePendingBindings() 类上的 executePendingBindings() 方法。问题是我无法在我的 UnitTests 中访问它
  • 知道如何在测试用例中获取绑定吗?
  • 我假设有一个支持绑定,在一些 setup() 方法中完成。您的测试没有显示任何绑定。绑定是必需的,因为这是执行表达式的地方。您需要使用YourLayoutBinding.inflate()YourLayoutBinding.bind()DataBindingUtil.setContentView() 对其进行实例化。
猜你喜欢
  • 2016-11-15
  • 2016-05-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-23
相关资源
最近更新 更多