LiveDataTest.java revision d069a4c914b2b43912fa6267b2f4c65408b6a4dc
1c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar/* 2c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar * Copyright (C) 2017 The Android Open Source Project 3c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar * 4c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar * Licensed under the Apache License, Version 2.0 (the "License"); 5c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar * you may not use this file except in compliance with the License. 6c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar * You may obtain a copy of the License at 7c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar * 8c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar * http://www.apache.org/licenses/LICENSE-2.0 9c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar * 10c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar * Unless required by applicable law or agreed to in writing, software 11c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar * distributed under the License is distributed on an "AS IS" BASIS, 12c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar * See the License for the specific language governing permissions and 14c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar * limitations under the License. 15c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar */ 16c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar 17c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyarpackage android.arch.lifecycle; 18c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar 19c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyarimport static android.arch.lifecycle.Lifecycle.Event.ON_CREATE; 20c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyarimport static android.arch.lifecycle.Lifecycle.Event.ON_DESTROY; 21c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyarimport static android.arch.lifecycle.Lifecycle.Event.ON_PAUSE; 22c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyarimport static android.arch.lifecycle.Lifecycle.Event.ON_RESUME; 23c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyarimport static android.arch.lifecycle.Lifecycle.Event.ON_START; 24c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyarimport static android.arch.lifecycle.Lifecycle.Event.ON_STOP; 25c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar 26c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyarimport static org.hamcrest.CoreMatchers.instanceOf; 27c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyarimport static org.hamcrest.CoreMatchers.is; 28c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyarimport static org.hamcrest.MatcherAssert.assertThat; 29c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyarimport static org.mockito.Matchers.anyBoolean; 30c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyarimport static org.mockito.Matchers.anyString; 31c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyarimport static org.mockito.Mockito.mock; 324d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyarimport static org.mockito.Mockito.never; 33c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyarimport static org.mockito.Mockito.reset; 34c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyarimport static org.mockito.Mockito.spy; 35c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyarimport static org.mockito.Mockito.verify; 36c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyarimport static org.mockito.Mockito.verifyNoMoreInteractions; 374d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyarimport static org.mockito.Mockito.when; 384d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar 39c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyarimport android.arch.core.executor.AppToolkitTaskExecutor; 40c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyarimport android.arch.lifecycle.util.InstantTaskExecutor; 41c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyarimport android.support.annotation.Nullable; 42c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar 43c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyarimport org.junit.After; 44c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyarimport org.junit.Before; 45c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyarimport org.junit.Test; 46c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyarimport org.junit.runner.RunWith; 47c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyarimport org.junit.runners.JUnit4; 48c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyarimport org.mockito.InOrder; 49c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyarimport org.mockito.Mockito; 50c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar 51c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar@SuppressWarnings({"unchecked"}) 52c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar@RunWith(JUnit4.class) 53c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyarpublic class LiveDataTest { 54c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar private PublicLiveData<String> mLiveData; 55c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar private LifecycleOwner mOwner; 56c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar private LifecycleRegistry mRegistry; 57c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar private MethodExec mActiveObserversChanged; 58c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar private boolean mInObserver; 59c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar 60c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar @Before 61c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar public void init() { 62c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar mLiveData = new PublicLiveData<>(); 63c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar mOwner = mock(LifecycleOwner.class); 64c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar mRegistry = new LifecycleRegistry(mOwner); 654d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar when(mOwner.getLifecycle()).thenReturn(mRegistry); 664d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar mActiveObserversChanged = mock(MethodExec.class); 67c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar mLiveData.activeObserversChanged = mActiveObserversChanged; 68c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar mInObserver = false; 69c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar } 704d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar 714d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar @Before 72c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar public void swapExecutorDelegate() { 73c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar AppToolkitTaskExecutor.getInstance().setDelegate(new InstantTaskExecutor()); 74c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar } 75c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar 76c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar @After 77c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar public void removeExecutorDelegate() { 78c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar AppToolkitTaskExecutor.getInstance().setDelegate(null); 79c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar } 804d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar 814d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar @Test 82c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar public void testObserverToggle() { 83c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar Observer<String> observer = (Observer<String>) mock(Observer.class); 84c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar mLiveData.observe(mOwner, observer); 854d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar 864d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar verify(mActiveObserversChanged, never()).onCall(anyBoolean()); 87c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar assertThat(mLiveData.hasObservers(), is(true)); 88c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar assertThat(mLiveData.hasActiveObservers(), is(false)); 89c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar 904d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar mLiveData.removeObserver(observer); 914d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar verify(mActiveObserversChanged, never()).onCall(anyBoolean()); 92c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar assertThat(mLiveData.hasObservers(), is(false)); 934d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar assertThat(mLiveData.hasActiveObservers(), is(false)); 94c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar } 95c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar 964d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar @Test 974d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar public void testActiveObserverToggle() { 98c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar Observer<String> observer = (Observer<String>) mock(Observer.class); 994d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar mLiveData.observe(mOwner, observer); 100c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar 101c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar verify(mActiveObserversChanged, never()).onCall(anyBoolean()); 1024d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar assertThat(mLiveData.hasObservers(), is(true)); 1034d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar assertThat(mLiveData.hasActiveObservers(), is(false)); 104c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar 1054d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar mRegistry.handleLifecycleEvent(ON_START); 106c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar verify(mActiveObserversChanged).onCall(true); 107c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar assertThat(mLiveData.hasActiveObservers(), is(true)); 108c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar reset(mActiveObserversChanged); 109c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar 110c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar mRegistry.handleLifecycleEvent(ON_STOP); 111c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar verify(mActiveObserversChanged).onCall(false); 112c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar assertThat(mLiveData.hasActiveObservers(), is(false)); 1134d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar assertThat(mLiveData.hasObservers(), is(true)); 114c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar 115c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar reset(mActiveObserversChanged); 116c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar mRegistry.handleLifecycleEvent(ON_START); 117c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar verify(mActiveObserversChanged).onCall(true); 118c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar assertThat(mLiveData.hasActiveObservers(), is(true)); 119c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar assertThat(mLiveData.hasObservers(), is(true)); 120c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar 121c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar reset(mActiveObserversChanged); 1224d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar mLiveData.removeObserver(observer); 123c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar verify(mActiveObserversChanged).onCall(false); 124c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar assertThat(mLiveData.hasActiveObservers(), is(false)); 125c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar assertThat(mLiveData.hasObservers(), is(false)); 126c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar 127c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar verifyNoMoreInteractions(mActiveObserversChanged); 128c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar } 129c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar 130c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar @Test 131c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar public void testReAddSameObserverTuple() { 132c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar Observer<String> observer = (Observer<String>) mock(Observer.class); 1334d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar mLiveData.observe(mOwner, observer); 134c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar mLiveData.observe(mOwner, observer); 135c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar assertThat(mLiveData.hasObservers(), is(true)); 136c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar } 137c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar 138c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar @Test 139c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar public void testAdd2ObserversWithSameOwnerAndRemove() { 140c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar Observer<String> o1 = (Observer<String>) mock(Observer.class); 141c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar Observer<String> o2 = (Observer<String>) mock(Observer.class); 142c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar mLiveData.observe(mOwner, o1); 143c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar mLiveData.observe(mOwner, o2); 144c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar assertThat(mLiveData.hasObservers(), is(true)); 145c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar verify(mActiveObserversChanged, never()).onCall(anyBoolean()); 146c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar 147c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar mRegistry.handleLifecycleEvent(ON_START); 148c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar verify(mActiveObserversChanged).onCall(true); 149c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar mLiveData.setValue("a"); 150c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar verify(o1).onChanged("a"); 151c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar verify(o2).onChanged("a"); 152c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar 153c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar mLiveData.removeObservers(mOwner); 154c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar 155c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar assertThat(mLiveData.hasObservers(), is(false)); 156c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar assertThat(mRegistry.getObserverCount(), is(0)); 157c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar } 158c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar 159c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar @Test 160c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar public void testAddSameObserverIn2LifecycleOwners() { 161c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar Observer<String> observer = (Observer<String>) mock(Observer.class); 1624d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar LifecycleOwner owner2 = mock(LifecycleOwner.class); 1634d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar LifecycleRegistry registry2 = new LifecycleRegistry(owner2); 1644d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar when(owner2.getLifecycle()).thenReturn(registry2); 1654d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar 166c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar mLiveData.observe(mOwner, observer); 167c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar Throwable throwable = null; 1684d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar try { 1694d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar mLiveData.observe(owner2, observer); 170c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar } catch (Throwable t) { 171c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar throwable = t; 172c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar } 173c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar assertThat(throwable, instanceOf(IllegalArgumentException.class)); 174c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar //noinspection ConstantConditions 175c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar assertThat(throwable.getMessage(), 176c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar is("Cannot add the same observer with different lifecycles")); 177c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar } 1784d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar 179c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar @Test 180c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar public void testRemoveDestroyedObserver() { 181c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar Observer<String> observer = (Observer<String>) mock(Observer.class); 182c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar mLiveData.observe(mOwner, observer); 183c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar mRegistry.handleLifecycleEvent(ON_START); 184c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar verify(mActiveObserversChanged).onCall(true); 185c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar assertThat(mLiveData.hasObservers(), is(true)); 186c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar assertThat(mLiveData.hasActiveObservers(), is(true)); 187c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar 188c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar reset(mActiveObserversChanged); 189c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar 190c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar mRegistry.handleLifecycleEvent(ON_DESTROY); 191c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar assertThat(mLiveData.hasObservers(), is(false)); 192c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar assertThat(mLiveData.hasActiveObservers(), is(false)); 193c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar verify(mActiveObserversChanged).onCall(false); 194c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar } 195c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar 196c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar @Test 197c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar public void testInactiveRegistry() { 198c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar Observer<String> observer = (Observer<String>) mock(Observer.class); 199c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar mRegistry.handleLifecycleEvent(ON_DESTROY); 200c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar mLiveData.observe(mOwner, observer); 201c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar assertThat(mLiveData.hasObservers(), is(false)); 202c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar } 203c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar 204c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar @Test 205c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar public void testNotifyActiveInactive() { 206c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar Observer<String> observer = (Observer<String>) mock(Observer.class); 207c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar mRegistry.handleLifecycleEvent(ON_CREATE); 208c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar mLiveData.observe(mOwner, observer); 209c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar mLiveData.setValue("a"); 210c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar verify(observer, never()).onChanged(anyString()); 211c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar mRegistry.handleLifecycleEvent(ON_START); 212c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar verify(observer).onChanged("a"); 213c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar 214c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar mLiveData.setValue("b"); 215c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar verify(observer).onChanged("b"); 216c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar 217c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar mRegistry.handleLifecycleEvent(ON_STOP); 218c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar mLiveData.setValue("c"); 219c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar verify(observer, never()).onChanged("c"); 220c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar 221c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar mRegistry.handleLifecycleEvent(ON_START); 222c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar verify(observer).onChanged("c"); 223c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar 224c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar reset(observer); 225c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar mRegistry.handleLifecycleEvent(ON_STOP); 226c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar mRegistry.handleLifecycleEvent(ON_START); 227c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar verify(observer, never()).onChanged(anyString()); 2284d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar } 2294d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar 2304d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar @Test 2314d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar public void testStopObservingOwner_onDestroy() { 2324d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar Observer<String> observer = (Observer<String>) mock(Observer.class); 2334d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar mRegistry.handleLifecycleEvent(ON_CREATE); 2344d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar mLiveData.observe(mOwner, observer); 2354d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar assertThat(mRegistry.getObserverCount(), is(1)); 2364d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar mRegistry.handleLifecycleEvent(ON_DESTROY); 2374d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar assertThat(mRegistry.getObserverCount(), is(0)); 2384d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar } 2394d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar 2404d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar @Test 2414d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar public void testStopObservingOwner_onStopObserving() { 2424d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar Observer<String> observer = (Observer<String>) mock(Observer.class); 2434d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar mRegistry.handleLifecycleEvent(ON_CREATE); 2444d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar mLiveData.observe(mOwner, observer); 2454d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar assertThat(mRegistry.getObserverCount(), is(1)); 2464d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar 2474d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar mLiveData.removeObserver(observer); 2484d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar assertThat(mRegistry.getObserverCount(), is(0)); 2494d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar } 2504d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar 2514d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar @Test 2524d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar public void testActiveChangeInCallback() { 2534d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar mRegistry.handleLifecycleEvent(ON_START); 2544d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar Observer<String> observer1 = spy(new Observer<String>() { 2554d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar @Override 2564d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar public void onChanged(@Nullable String s) { 2574d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar mRegistry.handleLifecycleEvent(ON_STOP); 2584d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar assertThat(mLiveData.hasObservers(), is(true)); 2594d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar assertThat(mLiveData.hasActiveObservers(), is(false)); 2604d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar } 2614d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar }); 2624d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar final Observer observer2 = mock(Observer.class); 2634d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar mLiveData.observe(mOwner, observer1); 2644d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar mLiveData.observe(mOwner, observer2); 2654d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar mLiveData.setValue("bla"); 2664d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar verify(observer1).onChanged(anyString()); 2674d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar verify(observer2, Mockito.never()).onChanged(anyString()); 2684d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar assertThat(mLiveData.hasObservers(), is(true)); 2694d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar assertThat(mLiveData.hasActiveObservers(), is(false)); 2704d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar } 2714d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar 2724d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar @Test 2734d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar public void testActiveChangeInCallback2() { 2744d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar Observer<String> observer1 = spy(new Observer<String>() { 2754d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar @Override 2764d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar public void onChanged(@Nullable String s) { 2774d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar assertThat(mInObserver, is(false)); 2784d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar mInObserver = true; 2794d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar mRegistry.handleLifecycleEvent(ON_START); 280c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar assertThat(mLiveData.hasActiveObservers(), is(true)); 281c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar mInObserver = false; 282c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar } 283c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar }); 284c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar final Observer observer2 = spy(new FailReentranceObserver()); 285c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar mLiveData.observeForever(observer1); 286c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar mLiveData.observe(mOwner, observer2); 287c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar mLiveData.setValue("bla"); 288c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar verify(observer1).onChanged(anyString()); 289c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar verify(observer2).onChanged(anyString()); 2904d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar assertThat(mLiveData.hasObservers(), is(true)); 291c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar assertThat(mLiveData.hasActiveObservers(), is(true)); 2924d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar } 293c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar 294c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar @Test 295c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar public void testObserverRemovalInCallback() { 296c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar mRegistry.handleLifecycleEvent(ON_START); 2974d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar Observer<String> observer = spy(new Observer<String>() { 2984d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar @Override 2994d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar public void onChanged(@Nullable String s) { 300c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar assertThat(mLiveData.hasObservers(), is(true)); 301c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar mLiveData.removeObserver(this); 302c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar assertThat(mLiveData.hasObservers(), is(false)); 303c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar } 304c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar }); 305c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar mLiveData.observe(mOwner, observer); 306c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar mLiveData.setValue("bla"); 307c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar verify(observer).onChanged(anyString()); 308 assertThat(mLiveData.hasObservers(), is(false)); 309 } 310 311 @Test 312 public void testObserverAdditionInCallback() { 313 mRegistry.handleLifecycleEvent(ON_START); 314 final Observer observer2 = spy(new FailReentranceObserver()); 315 Observer<String> observer1 = spy(new Observer<String>() { 316 @Override 317 public void onChanged(@Nullable String s) { 318 assertThat(mInObserver, is(false)); 319 mInObserver = true; 320 mLiveData.observe(mOwner, observer2); 321 assertThat(mLiveData.hasObservers(), is(true)); 322 assertThat(mLiveData.hasActiveObservers(), is(true)); 323 mInObserver = false; 324 } 325 }); 326 mLiveData.observe(mOwner, observer1); 327 mLiveData.setValue("bla"); 328 verify(observer1).onChanged(anyString()); 329 verify(observer2).onChanged(anyString()); 330 assertThat(mLiveData.hasObservers(), is(true)); 331 assertThat(mLiveData.hasActiveObservers(), is(true)); 332 } 333 334 @Test 335 public void testObserverWithoutLifecycleOwner() { 336 Observer<String> observer = (Observer<String>) mock(Observer.class); 337 mLiveData.setValue("boring"); 338 mLiveData.observeForever(observer); 339 verify(mActiveObserversChanged).onCall(true); 340 verify(observer).onChanged("boring"); 341 mLiveData.setValue("tihs"); 342 verify(observer).onChanged("tihs"); 343 mLiveData.removeObserver(observer); 344 verify(mActiveObserversChanged).onCall(false); 345 mLiveData.setValue("boring"); 346 reset(observer); 347 verify(observer, never()).onChanged(anyString()); 348 } 349 350 @Test 351 public void testSetValueDuringSetValue() { 352 mRegistry.handleLifecycleEvent(ON_START); 353 final Observer observer1 = spy(new Observer<String>() { 354 @Override 355 public void onChanged(String o) { 356 assertThat(mInObserver, is(false)); 357 mInObserver = true; 358 if (o.equals(("bla"))) { 359 mLiveData.setValue("gt"); 360 } 361 mInObserver = false; 362 } 363 }); 364 final Observer observer2 = spy(new FailReentranceObserver()); 365 mLiveData.observe(mOwner, observer1); 366 mLiveData.observe(mOwner, observer2); 367 mLiveData.setValue("bla"); 368 verify(observer1, Mockito.atMost(2)).onChanged("gt"); 369 verify(observer2, Mockito.atMost(2)).onChanged("gt"); 370 } 371 372 @Test 373 public void testRemoveDuringSetValue() { 374 mRegistry.handleLifecycleEvent(ON_START); 375 final Observer observer1 = spy(new Observer<String>() { 376 @Override 377 public void onChanged(String o) { 378 mLiveData.removeObserver(this); 379 } 380 }); 381 Observer<String> observer2 = (Observer<String>) mock(Observer.class); 382 mLiveData.observeForever(observer1); 383 mLiveData.observe(mOwner, observer2); 384 mLiveData.setValue("gt"); 385 verify(observer2).onChanged("gt"); 386 } 387 388 @Test 389 public void testDataChangeDuringStateChange() { 390 mRegistry.handleLifecycleEvent(ON_START); 391 mRegistry.addObserver(new LifecycleObserver() { 392 @OnLifecycleEvent(ON_STOP) 393 public void onStop() { 394 // change data in onStop, observer should not be called! 395 mLiveData.setValue("b"); 396 } 397 }); 398 Observer<String> observer = (Observer<String>) mock(Observer.class); 399 mLiveData.setValue("a"); 400 mLiveData.observe(mOwner, observer); 401 verify(observer).onChanged("a"); 402 mRegistry.handleLifecycleEvent(ON_PAUSE); 403 mRegistry.handleLifecycleEvent(ON_STOP); 404 verify(observer, never()).onChanged("b"); 405 406 mRegistry.handleLifecycleEvent(ON_RESUME); 407 verify(observer).onChanged("b"); 408 } 409 410 @Test 411 public void testNotCallInactiveWithObserveForever() { 412 mRegistry.handleLifecycleEvent(ON_START); 413 Observer<String> observer = (Observer<String>) mock(Observer.class); 414 Observer<String> observer2 = (Observer<String>) mock(Observer.class); 415 mLiveData.observe(mOwner, observer); 416 mLiveData.observeForever(observer2); 417 verify(mActiveObserversChanged).onCall(true); 418 reset(mActiveObserversChanged); 419 mRegistry.handleLifecycleEvent(ON_STOP); 420 verify(mActiveObserversChanged, never()).onCall(anyBoolean()); 421 mRegistry.handleLifecycleEvent(ON_START); 422 verify(mActiveObserversChanged, never()).onCall(anyBoolean()); 423 } 424 425 @Test 426 public void testRemoveDuringAddition() { 427 mRegistry.handleLifecycleEvent(ON_START); 428 mLiveData.setValue("bla"); 429 mLiveData.observeForever(new Observer<String>() { 430 @Override 431 public void onChanged(@Nullable String s) { 432 mLiveData.removeObserver(this); 433 } 434 }); 435 assertThat(mLiveData.hasActiveObservers(), is(false)); 436 InOrder inOrder = Mockito.inOrder(mActiveObserversChanged); 437 inOrder.verify(mActiveObserversChanged).onCall(true); 438 inOrder.verify(mActiveObserversChanged).onCall(false); 439 inOrder.verifyNoMoreInteractions(); 440 } 441 442 @Test 443 public void testRemoveDuringBringingUpToState() { 444 mLiveData.setValue("bla"); 445 mLiveData.observeForever(new Observer<String>() { 446 @Override 447 public void onChanged(@Nullable String s) { 448 mLiveData.removeObserver(this); 449 } 450 }); 451 mRegistry.handleLifecycleEvent(ON_RESUME); 452 assertThat(mLiveData.hasActiveObservers(), is(false)); 453 InOrder inOrder = Mockito.inOrder(mActiveObserversChanged); 454 inOrder.verify(mActiveObserversChanged).onCall(true); 455 inOrder.verify(mActiveObserversChanged).onCall(false); 456 inOrder.verifyNoMoreInteractions(); 457 } 458 459 @SuppressWarnings("WeakerAccess") 460 static class PublicLiveData<T> extends LiveData<T> { 461 // cannot spy due to internal calls 462 public MethodExec activeObserversChanged; 463 464 @Override 465 protected void onActive() { 466 if (activeObserversChanged != null) { 467 activeObserversChanged.onCall(true); 468 } 469 } 470 471 @Override 472 protected void onInactive() { 473 if (activeObserversChanged != null) { 474 activeObserversChanged.onCall(false); 475 } 476 } 477 } 478 479 private class FailReentranceObserver<T> implements Observer<T> { 480 @Override 481 public void onChanged(@Nullable T t) { 482 assertThat(mInObserver, is(false)); 483 } 484 } 485 486 interface MethodExec { 487 void onCall(boolean value); 488 } 489} 490