2016-11-20 3 views
0

Я пытался использовать TDD и получил следующий код:TDD и ресурсы освободив

public class ViewModel extends BaseObservable { 

    private final Subscription subscription; 

    public ReleasesViewModel(Observable<List<Data>> model) { 

     subscription = model.subscribe(this::setData);  
    } 

    public void destroy() { //method is not under test 
     subscription.unsubscribe();  
    } 

    public List<Data> getData() { 
     return data; 
    } 

    public void setData(List<Data> data) { 
     this.data = data; 
    } 
} 

и мой тест для:

public class ViewModelTest { 

    @Test 
    public void getData() { 

     BehaviorSubject<List<Data>> observable = BehaviorSubject.create(); 
     ViewModel viewModel = new ViewModel(observable); 

     List<Data> dataList = Arrays.asList(mock(Data.class), mock(Data.class)); 
     observable.onNext(dataList); 

     assertTrue(viewModel.getData().equals(dataList)); 
    } 
} 

Вопрос заключается в следующем:

Я должен убедиться, что subscription.unsubscribe(); будет вызван для освобождения ресурсов, я могу обернуть подписку в некоторой оболочке и добавить зависимость через конструктор, но я чувствую, что могу нарушить инкапсуляцию класса ViewModel , После многоголоджинга я не нашел никакой подсказки для случая проверки освобождения памяти в практике TDD. Может ли кто-то указать мне на некоторые «лучшие практики» для этого случая.

+2

Почему переход в 'Subscription' в конструкторе нарушает инкапсуляцию - он уже является членом вашего класса ViewModel? Как это вводится в ваш текущий код, если не через конструктор? –

+0

Извините, это была небольшая ошибка в коде. Я получаю «подписку» от «модели», переданной через конструктор. –

+0

Почему «Подписка» должна проходить внутри «ViewModel»? –

ответ

0

может быть, у вас есть некоторый пример тестирования собственно MVVM

Это то, что я хотел бы сделать с помощью Mockito (только мое предпочтение, любой другой Mocking Framework будет делать либо ...):

public class ViewModelTest { 
    @Rule 
    public MockitoRule rule = MockitoJUnit.rule(); 
    @Mock 
    BehaviorSubject<List<Data>> observable; 
    @Mock 
    Subscription subscription; 
    List<Data> data = Collections.emptyList(); 

    @Test 
    public void Constructor_CalledWithObservable_subcribesSetDataMethod() { 
     // prepare 
     when(model.subscribe()).thenRetun(subscription); 

     // act 
     ViewModel viewModel = new ViewModel(observable); 

     // assert 
     verify(observable).subscribe(ViewModel::setData); 
    } 

    @Test 
    public void destroy_unsubscribes() { 
     // prepare 
     when(model.subscribe()).thenRetun(subscription);  
     ViewModel viewModel = new ViewModel(observable); 

     // act 
     viewModel.destroy();  

     // assert 
     verify(subscription).unsubscribe(); 
    } 
} 
+0

И что вы делаете в случае, если вы должны преобразовать наблюдателя в модель просмотра с помощью .cache() или .delay() или других методов? Например: ViewModel (наблюдаемый наблюдаемый) { subscription = model.cache(). Subscribe (this :: setData); –

+0

@DmitryBykov Не понимаю этого. Что такое * поведение, связанное с бизнесом, за этим звонком? Я имею в виду то, что «модель» хранит «наблюдаемый» - это деталь реализации, которая не должна тестироваться. То, что вы * можете * проверить, состоит в том, что 'subscribe (this :: setData)' вызывается только один раз (что уже делает метод проверки) –

+0

Я говорю о таких случаях, когда вы не можете издеваться над наблюдаемыми параметр в конструкторе 'public ViewModel (Observable имен) { subscription = names.filter (name -> name.contain (" Jon ")). subscribe(); } ' –

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