Skip to content

Commit 202857d

Browse files
committed
Add some tests
Change-Id: I2bd2fa7812350940aff0ba8bc239c9e5b90df55d
1 parent 877fb21 commit 202857d

File tree

4 files changed

+213
-1
lines changed

4 files changed

+213
-1
lines changed

app/build.gradle

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,9 @@ dependencies {
5454
implementation 'com.github.bumptech.glide:glide:4.6.1'
5555
annotationProcessor 'com.github.bumptech.glide:compiler:4.6.1'
5656

57+
// Used for FirestorePagingActivity
58+
implementation 'android.arch.paging:runtime:1.0.0-beta1'
59+
5760
// The following dependencies are not required to use the Firebase UI library.
5861
// They are used to make some aspects of the demo app implementation simpler for
5962
// demonstrative purposes, and you may find them useful in your own apps; YMMV.

firestore/build.gradle

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,4 +27,7 @@ dependencies {
2727
androidTestImplementation 'junit:junit:4.12'
2828
androidTestImplementation 'com.android.support.test:runner:1.0.1'
2929
androidTestImplementation 'com.android.support.test:rules:1.0.1'
30+
//noinspection GradleDynamicVersion
31+
androidTestImplementation 'org.mockito:mockito-android:2.15.+'
32+
androidTestImplementation 'android.arch.paging:runtime:1.0.0-beta1'
3033
}
Lines changed: 206 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,206 @@
1+
package com.firebase.ui.firestore;
2+
3+
import android.arch.lifecycle.Observer;
4+
import android.arch.paging.PageKeyedDataSource;
5+
import android.support.annotation.Nullable;
6+
import android.support.test.runner.AndroidJUnit4;
7+
8+
import com.firebase.ui.firestore.paging.FirestoreDataSource;
9+
import com.firebase.ui.firestore.paging.LoadingState;
10+
import com.firebase.ui.firestore.paging.PageKey;
11+
import com.google.android.gms.tasks.Tasks;
12+
import com.google.firebase.firestore.DocumentSnapshot;
13+
import com.google.firebase.firestore.FirebaseFirestore;
14+
import com.google.firebase.firestore.Query;
15+
import com.google.firebase.firestore.QuerySnapshot;
16+
17+
import org.junit.Before;
18+
import org.junit.Test;
19+
import org.junit.runner.RunWith;
20+
import org.mockito.Mock;
21+
import org.mockito.MockitoAnnotations;
22+
23+
import java.util.ArrayList;
24+
import java.util.List;
25+
import java.util.concurrent.CountDownLatch;
26+
27+
import static org.junit.Assert.assertEquals;
28+
import static org.mockito.ArgumentMatchers.any;
29+
import static org.mockito.ArgumentMatchers.anyLong;
30+
import static org.mockito.Mockito.mock;
31+
import static org.mockito.Mockito.when;
32+
33+
@RunWith(AndroidJUnit4.class)
34+
public class FirestoreDataSourceTest {
35+
36+
private static final String TAG = "DataSourceTest";
37+
38+
private FirebaseFirestore mFirestore;
39+
private FirestoreDataSource mDataSource;
40+
41+
@Mock Query mMockQuery;
42+
@Mock PageKeyedDataSource.LoadInitialCallback<PageKey, DocumentSnapshot> mInitialCallback;
43+
@Mock PageKeyedDataSource.LoadCallback<PageKey, DocumentSnapshot> mAfterCallback;
44+
45+
@Before
46+
public void setUp() throws Exception {
47+
MockitoAnnotations.initMocks(this);
48+
initMockQuery();
49+
50+
// Create a testing data source
51+
mDataSource = new FirestoreDataSource(mMockQuery);
52+
}
53+
54+
@Test
55+
public void testLoadInitial_success() throws Exception {
56+
mockQuerySuccess(new ArrayList<DocumentSnapshot>());
57+
58+
TestObserver<LoadingState> observer = new TestObserver<>(2);
59+
mDataSource.getLoadingState().observeForever(observer);
60+
61+
// Kick off an initial load of 20 items
62+
PageKeyedDataSource.LoadInitialParams<PageKey> params =
63+
new PageKeyedDataSource.LoadInitialParams<>(20, false);
64+
mDataSource.loadInitial(params, mInitialCallback);
65+
66+
// Should go from LOADING_INITIAL --> LOADED
67+
observer.await();
68+
observer.assertResults(LoadingState.LOADING_INITIAL, LoadingState.LOADED);
69+
}
70+
71+
@Test
72+
public void testLoadInitial_failure() throws Exception {
73+
mockQueryFailure("Could not get initial documents.");
74+
75+
TestObserver<LoadingState> observer = new TestObserver<>(2);
76+
mDataSource.getLoadingState().observeForever(observer);
77+
78+
// Kick off an initial load of 20 items
79+
PageKeyedDataSource.LoadInitialParams<PageKey> params =
80+
new PageKeyedDataSource.LoadInitialParams<>(20, false);
81+
mDataSource.loadInitial(params, mInitialCallback);
82+
83+
// Should go from LOADING_INITIAL --> ERROR
84+
observer.await();
85+
observer.assertResults(LoadingState.LOADING_INITIAL, LoadingState.ERROR);
86+
}
87+
88+
@Test
89+
public void testLoadAfter_success() throws Exception {
90+
mockQuerySuccess(new ArrayList<DocumentSnapshot>());
91+
92+
TestObserver<LoadingState> observer = new TestObserver<>(2);
93+
mDataSource.getLoadingState().observeForever(observer);
94+
95+
// Kick off an initial load of 20 items
96+
PageKey pageKey = new PageKey(null, null);
97+
PageKeyedDataSource.LoadParams<PageKey> params =
98+
new PageKeyedDataSource.LoadParams<>(pageKey, 20);
99+
mDataSource.loadAfter(params, mAfterCallback);
100+
101+
// Should go from LOADING_MORE --> LOADED
102+
observer.await();
103+
observer.assertResults(LoadingState.LOADING_MORE, LoadingState.LOADED);
104+
}
105+
106+
@Test
107+
public void testLoadAfter_failure() throws Exception {
108+
mockQueryFailure("Could not load more documents.");
109+
110+
TestObserver<LoadingState> observer = new TestObserver<>(2);
111+
mDataSource.getLoadingState().observeForever(observer);
112+
113+
// Kick off an initial load of 20 items
114+
PageKey pageKey = new PageKey(null, null);
115+
PageKeyedDataSource.LoadParams<PageKey> params =
116+
new PageKeyedDataSource.LoadParams<>(pageKey, 20);
117+
mDataSource.loadAfter(params, mAfterCallback);
118+
119+
// Should go from LOADING_MORE --> ERROR
120+
observer.await();
121+
observer.assertResults(LoadingState.LOADING_MORE, LoadingState.ERROR);
122+
}
123+
124+
@Test
125+
public void testLoadAfter_retry() throws Exception {
126+
mockQueryFailure("Could not load more documents.");
127+
128+
TestObserver<LoadingState> observer1 = new TestObserver<>(2);
129+
mDataSource.getLoadingState().observeForever(observer1);
130+
131+
// Kick off an initial load of 20 items
132+
PageKey pageKey = new PageKey(null, null);
133+
PageKeyedDataSource.LoadParams<PageKey> params =
134+
new PageKeyedDataSource.LoadParams<>(pageKey, 20);
135+
mDataSource.loadAfter(params, mAfterCallback);
136+
137+
// Should go from LOADING_MORE --> ERROR
138+
observer1.await();
139+
observer1.assertResults(LoadingState.LOADING_MORE, LoadingState.ERROR);
140+
141+
// Create a new observer
142+
TestObserver<LoadingState> observer2 = new TestObserver<>(3);
143+
mDataSource.getLoadingState().observeForever(observer2);
144+
145+
// Retry the load
146+
mockQuerySuccess(new ArrayList<DocumentSnapshot>());
147+
mDataSource.retry();
148+
149+
// Should go from ERROR --> LOADING_MORE --> SUCCESS
150+
observer2.await();
151+
observer2.assertResults(LoadingState.ERROR, LoadingState.LOADING_MORE, LoadingState.LOADED);
152+
}
153+
154+
private void initMockQuery() {
155+
when(mMockQuery.startAfter(any())).thenReturn(mMockQuery);
156+
when(mMockQuery.endBefore(any())).thenReturn(mMockQuery);
157+
when(mMockQuery.limit(anyLong())).thenReturn(mMockQuery);
158+
}
159+
160+
private void mockQuerySuccess(List<DocumentSnapshot> snapshots) {
161+
QuerySnapshot mockSnapshot = mock(QuerySnapshot.class);
162+
when(mockSnapshot.getDocuments()).thenReturn(snapshots);
163+
164+
when(mMockQuery.get()).thenReturn(Tasks.forResult(mockSnapshot));
165+
}
166+
167+
private void mockQueryFailure(String message) {
168+
when(mMockQuery.get())
169+
.thenReturn(Tasks.<QuerySnapshot>forException(new Exception(message)));
170+
}
171+
172+
private static class TestObserver<T> implements Observer<T> {
173+
174+
private final List<T> mResults = new ArrayList<>();
175+
private final CountDownLatch mLatch;
176+
177+
public TestObserver(int expectedCount) {
178+
mLatch = new CountDownLatch(expectedCount);
179+
}
180+
181+
@Override
182+
public void onChanged(@Nullable T t) {
183+
if (t != null) {
184+
mResults.add(t);
185+
mLatch.countDown();
186+
}
187+
}
188+
189+
public List<T> getResults() {
190+
return mResults;
191+
}
192+
193+
public void await() throws InterruptedException {
194+
mLatch.await();
195+
}
196+
197+
public void assertResults(T... results) {
198+
assertEquals(results.length, mResults.size());
199+
200+
for (int i = 0; i < mResults.size(); i++) {
201+
assertEquals(mResults.get(i), results[i]);
202+
}
203+
}
204+
205+
}
206+
}

firestore/src/main/java/com/firebase/ui/firestore/paging/FirestoreDataSource.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,6 @@ public void loadInitial(@NonNull final LoadInitialParams<PageKey> params,
6767
protected void setResult(@NonNull QuerySnapshot snapshot) {
6868
PageKey nextPage = getNextPageKey(snapshot);
6969
callback.onResult(snapshot.getDocuments(), null, nextPage);
70-
7170
}
7271
})
7372
.addOnFailureListener(new OnLoadFailureListener() {
@@ -179,6 +178,7 @@ private abstract class OnLoadSuccessListener implements OnSuccessListener<QueryS
179178

180179
@Override
181180
public void onSuccess(QuerySnapshot snapshot) {
181+
setResult(snapshot);
182182
mLoadingState.postValue(LoadingState.LOADED);
183183
mRetryRunnable = null;
184184
}

0 commit comments

Comments
 (0)