MediatorLiveDataTest.java revision 6ca8525782f16bcb4403dc692a1fefd77934aa31
1/*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.support.lifecycle;
18
19import static org.hamcrest.CoreMatchers.is;
20import static org.hamcrest.MatcherAssert.assertThat;
21import static org.mockito.Matchers.any;
22import static org.mockito.Mockito.mock;
23import static org.mockito.Mockito.never;
24import static org.mockito.Mockito.reset;
25import static org.mockito.Mockito.verify;
26import static org.mockito.Mockito.when;
27
28import android.support.test.filters.SmallTest;
29
30import com.android.support.executors.AppToolkitTaskExecutor;
31import com.android.support.lifecycle.util.InstantTaskExecutor;
32
33import org.junit.Before;
34import org.junit.Test;
35import org.junit.runner.RunWith;
36import org.junit.runners.JUnit4;
37
38@SuppressWarnings("unchecked")
39@SmallTest
40@RunWith(JUnit4.class)
41public class MediatorLiveDataTest {
42
43    private LifecycleOwner mOwner;
44    private LifecycleRegistry mRegistry;
45    private MediatorLiveData<String> mMediator;
46    private LiveData<String> mSource;
47    private boolean mSourceActive;
48
49    @Before
50    public void setup() {
51        mOwner = mock(LifecycleOwner.class);
52        mRegistry = new LifecycleRegistry(mOwner);
53        when(mOwner.getLifecycle()).thenReturn(mRegistry);
54        mMediator = new MediatorLiveData<>();
55        mSource = new LiveData<String>() {
56            @Override
57            protected void onActive() {
58                mSourceActive = true;
59            }
60
61            @Override
62            protected void onInactive() {
63                mSourceActive = false;
64            }
65        };
66        mSourceActive = false;
67        mMediator.observe(mOwner, mock(Observer.class));
68        mRegistry.handleLifecycleEvent(Lifecycle.ON_CREATE);
69        mRegistry.handleLifecycleEvent(Lifecycle.ON_START);
70    }
71
72    @Before
73    public void swapExecutorDelegate() {
74        AppToolkitTaskExecutor.getInstance().setDelegate(new InstantTaskExecutor());
75    }
76
77    @Test
78    public void testSingleDelivery() {
79        Observer observer = mock(Observer.class);
80        mMediator.addSource(mSource, observer);
81        mSource.setValue("flatfoot");
82        verify(observer).onChanged("flatfoot");
83        mRegistry.handleLifecycleEvent(Lifecycle.ON_STOP);
84        reset(observer);
85        verify(observer, never()).onChanged(any());
86    }
87
88    @Test
89    public void testChangeWhileInactive() {
90        Observer observer = mock(Observer.class);
91        mMediator.addSource(mSource, observer);
92        mMediator.observe(mOwner, mock(Observer.class));
93        mSource.setValue("one");
94        verify(observer).onChanged("one");
95        mRegistry.handleLifecycleEvent(Lifecycle.ON_STOP);
96        reset(observer);
97        mSource.setValue("flatfoot");
98        mRegistry.handleLifecycleEvent(Lifecycle.ON_START);
99        verify(observer).onChanged("flatfoot");
100    }
101
102
103    @Test
104    public void testAddSourceToActive() {
105        mSource.setValue("flatfoot");
106        Observer observer = mock(Observer.class);
107        mMediator.addSource(mSource, observer);
108        verify(observer).onChanged("flatfoot");
109    }
110
111    @Test
112    public void testAddSourceToInActive() {
113        mSource.setValue("flatfoot");
114        mRegistry.handleLifecycleEvent(Lifecycle.ON_STOP);
115        Observer observer = mock(Observer.class);
116        mMediator.addSource(mSource, observer);
117        verify(observer, never()).onChanged(any());
118        mRegistry.handleLifecycleEvent(Lifecycle.ON_START);
119        verify(observer).onChanged("flatfoot");
120    }
121
122    @Test
123    public void testRemoveSource() {
124        mSource.setValue("flatfoot");
125        Observer observer = mock(Observer.class);
126        mMediator.addSource(mSource, observer);
127        verify(observer).onChanged("flatfoot");
128        mMediator.removeSource(mSource);
129        reset(observer);
130        mSource.setValue("failure");
131        verify(observer, never()).onChanged(any());
132    }
133
134    @Test
135    public void testSourceInactive() {
136        Observer observer = mock(Observer.class);
137        mMediator.addSource(mSource, observer);
138        assertThat(mSourceActive, is(true));
139        mRegistry.handleLifecycleEvent(Lifecycle.ON_STOP);
140        assertThat(mSourceActive, is(false));
141        mRegistry.handleLifecycleEvent(Lifecycle.ON_START);
142        assertThat(mSourceActive, is(true));
143    }
144
145    @Test
146    public void testNoLeakObserver() {
147        // Imitates a destruction of a ViewModel: a listener of LiveData is destroyed,
148        // a reference to MediatorLiveData is cleaned up. In this case we shouldn't leak
149        // MediatorLiveData as an observer of mSource.
150        assertThat(mSource.getObserverCount(), is(0));
151        Observer observer = mock(Observer.class);
152        mMediator.addSource(mSource, observer);
153        assertThat(mSource.getObserverCount(), is(1));
154        mRegistry.handleLifecycleEvent(Lifecycle.ON_STOP);
155        mRegistry.handleLifecycleEvent(Lifecycle.ON_DESTROY);
156        mMediator = null;
157        assertThat(mSource.getObserverCount(), is(0));
158    }
159
160    @Test
161    public void testMultipleSources() {
162        Observer observer1 = mock(Observer.class);
163        mMediator.addSource(mSource, observer1);
164        MutableLiveData<Integer> source2 = new MutableLiveData<>();
165        Observer observer2 = mock(Observer.class);
166        mMediator.addSource(source2, observer2);
167        mSource.setValue("flatfoot");
168        verify(observer1).onChanged("flatfoot");
169        verify(observer2, never()).onChanged(any());
170        reset(observer1, observer2);
171        source2.setValue(1703);
172        verify(observer1, never()).onChanged(any());
173        verify(observer2).onChanged(1703);
174        reset(observer1, observer2);
175        mRegistry.handleLifecycleEvent(Lifecycle.ON_STOP);
176        mSource.setValue("failure");
177        source2.setValue(0);
178        verify(observer1, never()).onChanged(any());
179        verify(observer2, never()).onChanged(any());
180    }
181}
182