2016-02-06 2 views
2

Я искал в Интернете, но я не могу узнать, как тестирование улучшилось с помощью MVVM. Я получаю идею наличия viewModel, который взаимодействует с представлением, но я не знаю, как бы написать хорошие тестовые примеры с MVVM. У меня есть следующее ViewModel в уже Android:Как проверить MVVM с DataBinding на Android

public class ViewModel extends BaseObservable { 
    private long countDownTime; 
    private MyCountDownTimer mCountDownTimer; 
    private final String TAG = getClass().getSimpleName(); 

    @Bindable  
    public long getCountDownTime() { 
     return countDownTime; 
    } 


    public void setCountDownTime(long countDownTime) { 
     this.countDownTime = countDownTime; 

     notifyPropertyChanged((int) BR.countDownTime); 
     Log.d(TAG,"prime tick:"+countDownTime); 
    } 

    public void startCounting(Long milli){ 
     mCountDownTimer.restartTimer(milli); 
    } 
} 

, а затем у меня есть представление XML, который использует его. У меня также есть активность, которая фактически связывает xml с этим представлением. Эта деятельность выглядит следующим образом:

public class MainActivity extends FragmentActivity { 
    CountdownBinder mCountdownBinder; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 

     //setContentView(R.layout.activity_main); 
     mCountdownBinder = DataBindingUtil.setContentView(this, R.layout.activity_main); 

     //Lets reference our textview just for fun 
     mCountdownBinder.tvGreen.setText("initial text"); 
     ViewModel viewModel = ViewModel.instance(); 

     //now tell databinding about your viewModel below 
     mCountdownBinder.setViewModel(viewModel); 
     viewModel.startCounting(200000L); 
    } 
} 

Теперь я настолько смущен, что это делает тестирование лучше. Я читал об этом, но мне нужен пример реального мира. Этот код от blog here, если это имеет значение.

По-видимому, я могу легче проверить свои модульные тесты? Будет ли я проверять только viewModel в MVVM? Что нужно тестировать в первую очередь?

ответ

3

Вы правы, предположив, что вы только тестируете модель ViewModel и модель. Сам пользовательский интерфейс не тестируется с помощью модульных тестов, хотя вы также можете выполнять автоматические тесты пользовательского интерфейса, которые отличаются от единичного теста.

На данный момент ваш примерный класс не очень дружественный к модулю. Одна из главных вещей, которую пытается выполнить MVVM (кроме разделения проблем), - это отделить ваш код. Ваша ViewModel должна содержать только логику представления, но не бизнес-логику. Это входит в слой модели MVVM.

Ваш ViewModel тесно связан, потому что вы создаете MyCountDownTimer внутри вашей модели ViewModel. Из-за этого вы больше не можете выполнять модульный тест, так как каждый раз, когда вы тестируете класс ViewModel, вы также проверите MyCountDownTimer. Это превращает ваш модульный тест в интеграционный тест (тестирование нескольких компонентов, работающих вместе).

Единичные тесты для каждого определения должны тестировать только определенный тип/класс или определенный кодовый блок. Другими словами, блок кода, отсюда и название: unit test. Для этого вам необходимо отделить зависимости вашего объекта, который вы хотите проверить.

Вы отделяете свои объекты, разделяя их на интерфейс и реализацию, а затем вставляете конкретную реализацию в свой объект, как правило, через инъекцию конструктора.

Например:

public class ViewModel extends BaseObservable { 
    private long countDownTime; 
    // Use final keyword here, so mCountDownTimer can only be set in the constructor and never changed 
    // this enforces the the classes invariants and once initialized, you'll be sure 
    // that it never can be null, so no need to do null checks before using 
    private final MyCountDownTimerInterface mCountDownTimer; 
    private final String TAG = getClass().getSimpleName(); 

    public ViewModel(MyCountDownTimerInterface mCountDownTimer) { 
     if(countDownTimer == null) { 
      throw new IllegalArgumentException("countDownTimer can't be null. "); 
     } 

     this.mCountDownTimer = countDownTimer; 
    } 

    @Bindable 
    public long getCountDownTime() { 
     return countDownTime; 
    } 


    public void setCountDownTime(long countDownTime) { 
     this.countDownTime = countDownTime; 

     notifyPropertyChanged((int) BR.countDownTime); 
    } 

    public void startCounting(Long milli) { 
     this.mCountDownTimer.restartTimer(milli); 
    } 
} 

Теперь вы можете проверить свой ViewModel без конкретного экземпляра вашего MyCountDownTimer класса.

Поскольку ваш пример содержит только поведение и не испытывать результат, вы должны сделать тест поведения в вашем, как

  • Если я позвоню startCounting(10L), то restartTimer(10L) должен быть назван в MyCountDownTimerInterfaceиgetCountDownTime() сусла возврат 10L.

Для этого вам нужно будет издеваться над интерфейсом MyCountDownTimerInterface и передать обманутый объект внутри. Мошки могут быть настроены для проверки того, что определенный метод издевающегося интерфейса вызывается с определенным параметром.

Я не могу предложить вам какой-либо код для этого, так как я не знаком с фреймворками Java/Android Mock. Я разработчик C# /. NET. Но если вы не знаете, как насмехаться над интерфейсом для теста, управляемого поведением, задайте новый вопрос здесь, на StackOverflow :)

+0

Эй, действительно, оцените отзывы. Каким будет ваше тестирование CountDownTimerInterface. Имеет смысл. Но в моем случае, какова была бы модель? – j2emanue

+1

Нет, я не тестирую 'CountDownTimerInterface'. Это насмехается. Я тестирую поведение ViewModel (так как в этом примере нет данных для тестирования). В вашем примере вы используете «MyCountDownTimer», и невозможно проверить ваш «ViewModel» изолированно, потому что всякий раз, когда вы вызываете 'this.mCountDownTimer.something', вы будете тестировать счетчик, а не модель вашего представления. Я удалил эту связь, заменив реализацию конкретного счетчика интерфейсом, и этот интерфейс будет издеваться во время теста (не используя настоящий класс MyCountDownTimer) – Tseng

+1

@ j2emanue: Здесь ссылка на конструкцию, управляемую поведением (BDD) https://en.wikipedia.org/wiki/Behavior-driven_development – Tseng

Смежные вопросы