Android: как установить частные MutableLiveData в модульном тесте

Я пытаюсь проверить свой 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) и получателя с помощью myPublicLiveData. Я имею в виду, когда я открываю и геттер, и сеттер моего поля private, почему бы мне просто не сделать его общедоступным?

Вот мой текущий подход к тестированию моих 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())
}

Я надеюсь, что есть способ лучше, чем писать собственный сеттер для всех изменяемых данных (у меня их более 20, и это просто уродливый шаблонный код). Может я что-то здесь неправильно понял.

Имейте в виду, что я новичок в разработке Android и в концепции MVVM и особенно Livedata.

Я ценю любую помощь, спасибо!


person Andrew    schedule 16.09.2020    source источник


Ответы (3)


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

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

Извините, но этот код не имеет смысла. Если вам абсолютно необходимо идти этим путем, то нет необходимости использовать двойные поля, так как вы все равно открываете изменяемое состояние.

При этом я бы сказал, что вам нужно прибегнуть к этому, и обычно это запах кода. Я не могу видеть всю вашу модель представления, но я предполагаю, что у вас есть общедоступная функция (или некоторый код инициализации), которая запускает некоторую работу и передает данные в живые данные, и это то, что вы должны протестировать вместо этого. Если вы хотите загрузить свою модель полного представления, я могу попытаться предложить подход к тестированию, обновив ответ. Ваше здоровье!

person Marco Pierucci    schedule 16.09.2020
comment
Я попытаюсь переосмыслить свой подход, возможно, мне даже не нужно тестировать эти конкретные функции внутри моей модели представления, потому что они просто используют другие общедоступные функции из моих моделей, которые я уже тестировал. Я не думаю, что могу опубликовать всю Viewmodel, потому что в ней более 400 строк кода (отвечает за navgraph с 3 фрагментами и большим количеством edittext) - person Andrew; 17.09.2020

Хорошо, это может быть не лучший ответ, но для меня это работает. На данный момент меня действительно не волнует, о нет, но это неправильно в программировании 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<T> и два публичных поля secondDropDownVisibility и shippingFirstDdText типа LiveData<T>

Ваше здоровье

person Andrew    schedule 21.09.2020

Вы должны просто сделать MutableLiveData общедоступным, если вам нужно изменить его извне (без каких-либо дополнительных гарантий для методов).

Если бы вы использовали привязку данных, вы бы открыли ObservableField, который также доступен для чтения и записи.

person EpicPandaForce    schedule 16.09.2020
comment
Но мне нужно только изменить MutableLiveData в моих ТЕСТах и больше нигде. Я очень сомневаюсь, что это рекомендуемый способ ... Зачем мне делать что-то общедоступное, что НОРМАЛЬНО частное, только для проверки? Это ужасно. И нет, я не использую observableField для привязки данных (никто не должен этого делать), я использую обычные жизненные данные с учетом жизненного цикла. - person Andrew; 16.09.2020
comment
выставление полей только для тестовых целей - это обычно запах кода, это означает, что вы проектируете не с расчетом на тестирование. - person Marco Pierucci; 17.09.2020
comment
Если вы не можете получить к нему доступ извне, то не открывайте его из тестов ????????‍♀️ - person EpicPandaForce; 17.09.2020