From 0a6c8b10db3d46a125ce00e292eda97cbe0fe434 Mon Sep 17 00:00:00 2001 From: Allan Hasegawa Date: Sun, 30 Jul 2017 20:27:02 -0300 Subject: [PATCH] Refactored our UseCases so we can test them --- app/build.gradle | 12 +- .../java/io/catter2/FavoritesActivity.java | 5 +- .../main/java/io/catter2/ListActivity.java | 10 +- .../cat_api/FetchCatImagesUseCase.java | 32 ++--- .../io/catter2/cat_api/RetrofitTheCatAPI.java | 36 +++++- .../java/io/catter2/cat_api/TheCatAPI.java | 9 ++ .../catter2/favorites/AddFavoriteUseCase.java | 6 +- .../favorites/FavoritesRepository.java | 116 +---------------- .../favorites/GetFavoritesUseCase.java | 6 +- .../SharedPrefFavoritesRepository.java | 121 ++++++++++++++++++ .../cat_api/FetchCatImagesUseCaseTest.java | 84 ++++++++++++ .../favorites/AddFavoriteUseCaseTest.java | 66 ++++++++++ .../favorites/GetFavoritesUseCaseTest.java | 90 +++++++++++++ 13 files changed, 443 insertions(+), 150 deletions(-) create mode 100644 app/src/main/java/io/catter2/cat_api/TheCatAPI.java create mode 100644 app/src/main/java/io/catter2/favorites/SharedPrefFavoritesRepository.java create mode 100644 app/src/test/java/io/catter2/cat_api/FetchCatImagesUseCaseTest.java create mode 100644 app/src/test/java/io/catter2/favorites/AddFavoriteUseCaseTest.java create mode 100644 app/src/test/java/io/catter2/favorites/GetFavoritesUseCaseTest.java diff --git a/app/build.gradle b/app/build.gradle index 661c050..0471511 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -33,11 +33,11 @@ dependencies { leonids : '1.3.1', junit : '4.12', + mockito : '2.+', + + espresso : '2.2.2', ] - androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { - exclude group: 'com.android.support', module: 'support-annotations' - }) compile "com.android.support:appcompat-v7:$versions.supportLib" compile "com.android.support:design:$versions.supportLib" compile "com.squareup.picasso:picasso:$versions.picasso" @@ -48,5 +48,11 @@ dependencies { exclude group: 'stax', module: 'stax' exclude group: 'xpp3', module: 'xpp3' }) + testCompile "junit:junit:$versions.junit" + testCompile "org.mockito:mockito-core:$versions.mockito" + + androidTestCompile("com.android.support.test.espresso:espresso-core:$versions.espresso", { + exclude group: 'com.android.support', module: 'support-annotations' + }) } diff --git a/app/src/main/java/io/catter2/FavoritesActivity.java b/app/src/main/java/io/catter2/FavoritesActivity.java index 66aae5b..e716cb5 100644 --- a/app/src/main/java/io/catter2/FavoritesActivity.java +++ b/app/src/main/java/io/catter2/FavoritesActivity.java @@ -13,7 +13,9 @@ import java.util.List; +import io.catter2.favorites.FavoritesRepository; import io.catter2.favorites.GetFavoritesUseCase; +import io.catter2.favorites.SharedPrefFavoritesRepository; public class FavoritesActivity extends AppCompatActivity { @@ -62,7 +64,8 @@ public void onClick(View view) { } Log.d(TAG, "UserToken: " + userToken); - getFavoritesUseCase = new GetFavoritesUseCase(this, userToken); + FavoritesRepository favoritesRepository = new SharedPrefFavoritesRepository(this, userToken); + getFavoritesUseCase = new GetFavoritesUseCase(favoritesRepository); getFavoritesUseCase.getFavorites(new GetFavoritesUseCase.Callback() { @Override public void favoriteUrlsUpdated(List favoriteUrls) { diff --git a/app/src/main/java/io/catter2/ListActivity.java b/app/src/main/java/io/catter2/ListActivity.java index fb118af..6807af0 100644 --- a/app/src/main/java/io/catter2/ListActivity.java +++ b/app/src/main/java/io/catter2/ListActivity.java @@ -17,7 +17,11 @@ import java.util.List; import io.catter2.cat_api.FetchCatImagesUseCase; +import io.catter2.cat_api.RetrofitTheCatAPI; +import io.catter2.cat_api.TheCatAPI; import io.catter2.favorites.AddFavoriteUseCase; +import io.catter2.favorites.FavoritesRepository; +import io.catter2.favorites.SharedPrefFavoritesRepository; public class ListActivity extends AppCompatActivity { private static String TAG = "List"; @@ -60,8 +64,10 @@ public void imageClicked(ImageView view, String url) { recyclerView.setAdapter(adapter); - addFavoriteUseCase = new AddFavoriteUseCase(this, userToken); - fetchCatImagesUseCase = new FetchCatImagesUseCase(); + FavoritesRepository favoritesRepository = new SharedPrefFavoritesRepository(this, userToken); + addFavoriteUseCase = new AddFavoriteUseCase(favoritesRepository); + TheCatAPI catAPI = new RetrofitTheCatAPI(); + fetchCatImagesUseCase = new FetchCatImagesUseCase(catAPI); fetchCatImagesUseCase.getImagesUrls(new FetchCatImagesUseCase.Callback() { @Override diff --git a/app/src/main/java/io/catter2/cat_api/FetchCatImagesUseCase.java b/app/src/main/java/io/catter2/cat_api/FetchCatImagesUseCase.java index ccb057d..b9a1cc9 100644 --- a/app/src/main/java/io/catter2/cat_api/FetchCatImagesUseCase.java +++ b/app/src/main/java/io/catter2/cat_api/FetchCatImagesUseCase.java @@ -1,45 +1,31 @@ package io.catter2.cat_api; -import android.util.Log; - import java.util.ArrayList; import java.util.List; -import retrofit2.Call; -import retrofit2.Response; -import retrofit2.Retrofit; -import retrofit2.converter.simplexml.SimpleXmlConverterFactory; - public class FetchCatImagesUseCase { public interface Callback { void imagesUrls(List urls); } - private static String TAG = "FetchCatImagesUseCase"; + private TheCatAPI catAPI; + + public FetchCatImagesUseCase(TheCatAPI catAPI) { + this.catAPI = catAPI; + } public void getImagesUrls(final Callback callback) { - Retrofit retrofit = new Retrofit.Builder() - .baseUrl("http://thecatapi.com/api/") - .addConverterFactory(SimpleXmlConverterFactory.create()) - .build(); - RetrofitTheCatAPI retrofitTheCatApi = retrofit.create(RetrofitTheCatAPI.class); - retrofitTheCatApi.listCatsWithHat().enqueue(new retrofit2.Callback() { + catAPI.getCatsWithHats(new TheCatAPI.Callback() { @Override - public void onResponse(Call call, Response response) { + public void response(CatImagesModel response) { ArrayList imageUrls = new ArrayList<>(); - if (response.body().catImages != null) { - for (CatImageModel img : response.body().catImages) { - Log.d(TAG, "Found: " + img.url); + if (response != null) { + for (CatImageModel img : response.catImages) { imageUrls.add(img.url); } } callback.imagesUrls(imageUrls); } - - @Override - public void onFailure(Call call, Throwable t) { - Log.e(TAG, "Error fetching cat images", t); - } }); } } diff --git a/app/src/main/java/io/catter2/cat_api/RetrofitTheCatAPI.java b/app/src/main/java/io/catter2/cat_api/RetrofitTheCatAPI.java index f1ea1e1..b7eedf6 100644 --- a/app/src/main/java/io/catter2/cat_api/RetrofitTheCatAPI.java +++ b/app/src/main/java/io/catter2/cat_api/RetrofitTheCatAPI.java @@ -1,9 +1,39 @@ package io.catter2.cat_api; +import android.util.Log; + import retrofit2.Call; +import retrofit2.Response; +import retrofit2.Retrofit; +import retrofit2.converter.simplexml.SimpleXmlConverterFactory; import retrofit2.http.GET; -public interface RetrofitTheCatAPI { - @GET("images/get?format=xml&results_per_page=20&category=hats") - Call listCatsWithHat(); +import static android.content.ContentValues.TAG; + +public class RetrofitTheCatAPI implements TheCatAPI { + interface RetrofitCatService { + @GET("images/get?format=xml&results_per_page=20&category=hats") + Call listCatsWithHat(); + } + + @Override + public void getCatsWithHats(final Callback callback) { + Retrofit retrofit = new Retrofit.Builder() + .baseUrl("http://thecatapi.com/api/") + .addConverterFactory(SimpleXmlConverterFactory.create()) + .build(); + RetrofitCatService retrofitCatService = retrofit.create(RetrofitCatService.class); + retrofitCatService.listCatsWithHat().enqueue(new retrofit2.Callback() { + @Override + public void onResponse(Call call, Response response) { + callback.response(response.body()); + } + + @Override + public void onFailure(Call call, Throwable t) { + Log.e(TAG, "Error fetching cat images", t); + callback.response(null); + } + }); + } } diff --git a/app/src/main/java/io/catter2/cat_api/TheCatAPI.java b/app/src/main/java/io/catter2/cat_api/TheCatAPI.java new file mode 100644 index 0000000..c41fd33 --- /dev/null +++ b/app/src/main/java/io/catter2/cat_api/TheCatAPI.java @@ -0,0 +1,9 @@ +package io.catter2.cat_api; + +public interface TheCatAPI { + interface Callback { + void response(CatImagesModel response); + } + + void getCatsWithHats(Callback callback); +} diff --git a/app/src/main/java/io/catter2/favorites/AddFavoriteUseCase.java b/app/src/main/java/io/catter2/favorites/AddFavoriteUseCase.java index fceeaee..14a02de 100644 --- a/app/src/main/java/io/catter2/favorites/AddFavoriteUseCase.java +++ b/app/src/main/java/io/catter2/favorites/AddFavoriteUseCase.java @@ -1,14 +1,12 @@ package io.catter2.favorites; -import android.content.Context; - import java.util.List; public class AddFavoriteUseCase { private FavoritesRepository repo; - public AddFavoriteUseCase(Context context, String userToken) { - repo = new FavoritesRepository(context, userToken); + public AddFavoriteUseCase(FavoritesRepository favoritesRepository) { + this.repo = favoritesRepository; } /** diff --git a/app/src/main/java/io/catter2/favorites/FavoritesRepository.java b/app/src/main/java/io/catter2/favorites/FavoritesRepository.java index 30e49a6..45f8a0d 100644 --- a/app/src/main/java/io/catter2/favorites/FavoritesRepository.java +++ b/app/src/main/java/io/catter2/favorites/FavoritesRepository.java @@ -1,128 +1,24 @@ package io.catter2.favorites; -import android.content.Context; -import android.content.SharedPreferences; -import android.util.Log; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashSet; import java.util.List; -import java.util.Set; - -import io.catter2.R; -public class FavoritesRepository { - public interface ChangeListener { +public interface FavoritesRepository { + interface ChangeListener { void onFavoritesChanged(List favorites); } - private static String SP_USER_FAVORITES_KEY = "user-favorites-urls-%s"; - private static String TAG = "FavoritesRepository"; - - private Context context; - private String userToken; - private ChangeListener changeListener; - private SharedPreferences.OnSharedPreferenceChangeListener sharedPrefListener; - - public FavoritesRepository(Context context, String userToken) { - this.context = context; - this.userToken = userToken; - } - /** * @return A list of favorites sorted by the time it was added. */ - public List getFavorites() { - SharedPreferences pref = getPref(); - String prefKey = getFavoritesKey(); - Set entriesSet = pref.getStringSet(prefKey, new HashSet()); - - ArrayList favorites = new ArrayList<>(entriesSet.size()); - for (String entry : entriesSet) { - String[] decoded = entry.split(";"); - favorites.add(new FavoriteModel(Long.valueOf(decoded[1]), decoded[0])); - } - - Collections.sort(favorites, new Comparator() { - @Override - public int compare(FavoriteModel o1, FavoriteModel o2) { - return (int) (o2.getTimeAdded() - o1.getTimeAdded()); - } - }); - - return favorites; - } + List getFavorites(); /** * @param model * @return A list of favorites sorted by the time it was added, with the newly added favorite. */ - public List addFavorite(FavoriteModel model) { - List oldModels = getFavorites(); + List addFavorite(FavoriteModel model); - boolean hasUrl = false; - for (FavoriteModel entry : oldModels) { - if (entry.getUrl().equals(model.getUrl())) { - hasUrl = true; - break; - } - } + void registerChangeListener(final ChangeListener listener); - if (hasUrl) { - return oldModels; - } - - ArrayList newList = new ArrayList<>(oldModels); - newList.add(model); - saveFavorites(newList); - - return newList; - } - - public void registerChangeListener(final ChangeListener listener) { - if (this.changeListener != null) { - throw new RuntimeException("Listener already registered."); - } - this.changeListener = listener; - this.sharedPrefListener = new SharedPreferences.OnSharedPreferenceChangeListener() { - @Override - public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { - Log.d(TAG, "Key changed: " + key); - String prefKey = String.format(SP_USER_FAVORITES_KEY, userToken); - if (key.equals(prefKey)) { - changeListener.onFavoritesChanged(getFavorites()); - } - } - }; - getPref().registerOnSharedPreferenceChangeListener(this.sharedPrefListener); - } - - public void clearChangeListener() { - this.changeListener = null; - if (this.sharedPrefListener != null) { - getPref().unregisterOnSharedPreferenceChangeListener(this.sharedPrefListener); - this.sharedPrefListener = null; - } - } - - private SharedPreferences getPref() { - String prefName = context.getString(R.string.pref_key_user_data); - return context.getSharedPreferences(prefName, Context.MODE_PRIVATE); - } - - private String getFavoritesKey() { - return String.format(SP_USER_FAVORITES_KEY, userToken); - } - - private void saveFavorites(ArrayList newList) { - HashSet newEntries = new HashSet<>(newList.size()); - - for (FavoriteModel entry : newList) { - newEntries.add(entry.getUrl() + ";" + entry.getTimeAdded()); - } - - getPref().edit().putStringSet(getFavoritesKey(), newEntries).apply(); - } + void clearChangeListener(); } diff --git a/app/src/main/java/io/catter2/favorites/GetFavoritesUseCase.java b/app/src/main/java/io/catter2/favorites/GetFavoritesUseCase.java index a6d42d3..e00dbe8 100644 --- a/app/src/main/java/io/catter2/favorites/GetFavoritesUseCase.java +++ b/app/src/main/java/io/catter2/favorites/GetFavoritesUseCase.java @@ -1,7 +1,5 @@ package io.catter2.favorites; -import android.content.Context; - import java.util.ArrayList; import java.util.List; @@ -12,8 +10,8 @@ public interface Callback { private FavoritesRepository repo; - public GetFavoritesUseCase(Context context, String userToken) { - this.repo = new FavoritesRepository(context, userToken); + public GetFavoritesUseCase(FavoritesRepository favoritesRepository) { + this.repo = favoritesRepository; } /** diff --git a/app/src/main/java/io/catter2/favorites/SharedPrefFavoritesRepository.java b/app/src/main/java/io/catter2/favorites/SharedPrefFavoritesRepository.java new file mode 100644 index 0000000..d8b18a5 --- /dev/null +++ b/app/src/main/java/io/catter2/favorites/SharedPrefFavoritesRepository.java @@ -0,0 +1,121 @@ +package io.catter2.favorites; + +import android.content.Context; +import android.content.SharedPreferences; +import android.util.Log; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import io.catter2.R; + +public class SharedPrefFavoritesRepository implements FavoritesRepository { + private static String SP_USER_FAVORITES_KEY = "user-favorites-urls-%s"; + private static String TAG = "SharedPrefFavoritesRepo"; + + private Context context; + private String userToken; + private ChangeListener changeListener; + private SharedPreferences.OnSharedPreferenceChangeListener sharedPrefListener; + + public SharedPrefFavoritesRepository(Context context, String userToken) { + this.context = context; + this.userToken = userToken; + } + + @Override + public List getFavorites() { + SharedPreferences pref = getPref(); + String prefKey = getFavoritesKey(); + Set entriesSet = pref.getStringSet(prefKey, new HashSet()); + + ArrayList favorites = new ArrayList<>(entriesSet.size()); + for (String entry : entriesSet) { + String[] decoded = entry.split(";"); + favorites.add(new FavoriteModel(Long.valueOf(decoded[1]), decoded[0])); + } + + Collections.sort(favorites, new Comparator() { + @Override + public int compare(FavoriteModel o1, FavoriteModel o2) { + return (int) (o2.getTimeAdded() - o1.getTimeAdded()); + } + }); + + return favorites; + } + + @Override + public List addFavorite(FavoriteModel model) { + List oldModels = getFavorites(); + + boolean hasUrl = false; + for (FavoriteModel entry : oldModels) { + if (entry.getUrl().equals(model.getUrl())) { + hasUrl = true; + break; + } + } + + if (hasUrl) { + return oldModels; + } + + ArrayList newList = new ArrayList<>(oldModels); + newList.add(model); + saveFavorites(newList); + + return newList; + } + + @Override + public void registerChangeListener(final ChangeListener listener) { + if (this.changeListener != null) { + throw new RuntimeException("Listener already registered."); + } + this.changeListener = listener; + this.sharedPrefListener = new SharedPreferences.OnSharedPreferenceChangeListener() { + @Override + public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { + Log.d(TAG, "Key changed: " + key); + String prefKey = String.format(SP_USER_FAVORITES_KEY, userToken); + if (key.equals(prefKey)) { + changeListener.onFavoritesChanged(getFavorites()); + } + } + }; + getPref().registerOnSharedPreferenceChangeListener(this.sharedPrefListener); + } + + @Override + public void clearChangeListener() { + this.changeListener = null; + if (this.sharedPrefListener != null) { + getPref().unregisterOnSharedPreferenceChangeListener(this.sharedPrefListener); + this.sharedPrefListener = null; + } + } + + private SharedPreferences getPref() { + String prefName = context.getString(R.string.pref_key_user_data); + return context.getSharedPreferences(prefName, Context.MODE_PRIVATE); + } + + private String getFavoritesKey() { + return String.format(SP_USER_FAVORITES_KEY, userToken); + } + + private void saveFavorites(ArrayList newList) { + HashSet newEntries = new HashSet<>(newList.size()); + + for (FavoriteModel entry : newList) { + newEntries.add(entry.getUrl() + ";" + entry.getTimeAdded()); + } + + getPref().edit().putStringSet(getFavoritesKey(), newEntries).apply(); + } +} diff --git a/app/src/test/java/io/catter2/cat_api/FetchCatImagesUseCaseTest.java b/app/src/test/java/io/catter2/cat_api/FetchCatImagesUseCaseTest.java new file mode 100644 index 0000000..60088d5 --- /dev/null +++ b/app/src/test/java/io/catter2/cat_api/FetchCatImagesUseCaseTest.java @@ -0,0 +1,84 @@ +package io.catter2.cat_api; + +import org.junit.Assert; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +import static org.hamcrest.CoreMatchers.equalTo; + +public class FetchCatImagesUseCaseTest { + @Test + public void testNoImages() throws InterruptedException { + StubAPI stub = new StubAPI(); + FetchCatImagesUseCase uc = useCase(stub); + + + final CountDownLatch latch = new CountDownLatch(1); + uc.getImagesUrls(new FetchCatImagesUseCase.Callback() { + @Override + public void imagesUrls(List urls) { + Assert.assertThat(urls.size(), equalTo(0)); + latch.countDown(); + } + }); + + stub.respond(new ArrayList()); + latch.await(10, TimeUnit.SECONDS); + } + + @Test + public void testTwoImages() throws InterruptedException { + StubAPI stub = new StubAPI(); + FetchCatImagesUseCase uc = useCase(stub); + + ArrayList responseUrls = new ArrayList<>(); + responseUrls.add("url0"); + responseUrls.add("url1"); + + final CountDownLatch latch = new CountDownLatch(1); + uc.getImagesUrls(new FetchCatImagesUseCase.Callback() { + @Override + public void imagesUrls(List urls) { + Assert.assertThat(urls.size(), equalTo(2)); + Assert.assertThat(urls.get(0), equalTo("url0")); + Assert.assertThat(urls.get(1), equalTo("url1")); + latch.countDown(); + } + }); + + stub.respond(responseUrls); + latch.await(10, TimeUnit.SECONDS); + } + + private FetchCatImagesUseCase useCase(TheCatAPI api) { + return new FetchCatImagesUseCase(api); + } + + class StubAPI implements TheCatAPI { + Callback callback; + + @Override + public void getCatsWithHats(Callback callback) { + this.callback = callback; + } + + public void respond(List urls) { + CatImagesModel response = new CatImagesModel(); + ArrayList images = new ArrayList<>(); + for (String url : urls) { + CatImageModel model = new CatImageModel(); + model.sourceUrl = url; + model.url = url; + model.id = url + "id"; + images.add(model); + } + response.catImages = images; + + callback.response(response); + } + } +} diff --git a/app/src/test/java/io/catter2/favorites/AddFavoriteUseCaseTest.java b/app/src/test/java/io/catter2/favorites/AddFavoriteUseCaseTest.java new file mode 100644 index 0000000..7bdd649 --- /dev/null +++ b/app/src/test/java/io/catter2/favorites/AddFavoriteUseCaseTest.java @@ -0,0 +1,66 @@ +package io.catter2.favorites; + +import org.junit.Assert; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.List; + +public class AddFavoriteUseCaseTest { + @Test + public void testAddTrue() { + StubRepo stub = new StubRepo(); + AddFavoriteUseCase uc = useCase(stub); + + boolean added = uc.addFavoriteUrl("url0"); + Assert.assertTrue(added); + } + + @Test + public void testAddFalse() { + StubRepo stub = new StubRepo(); + AddFavoriteUseCase uc = useCase(stub); + + stub.addModel = false; + + boolean added = uc.addFavoriteUrl("url0"); + Assert.assertFalse(added); + } + + private AddFavoriteUseCase useCase(FavoritesRepository repo) { + return new AddFavoriteUseCase(repo); + } + + private static class StubRepo implements FavoritesRepository { + ArrayList models; + boolean addModel; + + public StubRepo() { + addModel = true; + models = new ArrayList<>(); + } + + @Override + public List getFavorites() { + throw new RuntimeException("Not implemented"); + } + + @Override + public List addFavorite(FavoriteModel model) { + if (addModel) { + models.add(model); + } + return models; + } + + @Override + public void registerChangeListener(ChangeListener listener) { + throw new RuntimeException("Not implemented"); + } + + @Override + public void clearChangeListener() { + throw new RuntimeException("Not implemented"); + } + } +} diff --git a/app/src/test/java/io/catter2/favorites/GetFavoritesUseCaseTest.java b/app/src/test/java/io/catter2/favorites/GetFavoritesUseCaseTest.java new file mode 100644 index 0000000..cbb3fe0 --- /dev/null +++ b/app/src/test/java/io/catter2/favorites/GetFavoritesUseCaseTest.java @@ -0,0 +1,90 @@ +package io.catter2.favorites; + +import org.junit.Test; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.junit.Assert.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class GetFavoritesUseCaseTest { + @Test + public void testEmptyList() throws InterruptedException { + FavoritesRepository mock = mock(FavoritesRepository.class); + GetFavoritesUseCase uc = useCase(mock); + + // when + when(mock.getFavorites()).thenReturn(new ArrayList()); + + final CountDownLatch latch = new CountDownLatch(1); + uc.getFavorites(new GetFavoritesUseCase.Callback() { + @Override + public void favoriteUrlsUpdated(List favoriteUrls) { + assertThat(favoriteUrls.size(), equalTo(0)); + latch.countDown(); + } + }); + latch.await(10, TimeUnit.SECONDS); + } + + @Test + public void testSingleEleList() throws InterruptedException { + FavoritesRepository mock = mock(FavoritesRepository.class); + GetFavoritesUseCase uc = useCase(mock); + + // when + { + ArrayList mockList = new ArrayList<>(); + mockList.add(new FavoriteModel(10, "url-0")); + when(mock.getFavorites()).thenReturn(mockList); + } + + final CountDownLatch latch = new CountDownLatch(1); + uc.getFavorites(new GetFavoritesUseCase.Callback() { + @Override + public void favoriteUrlsUpdated(List favoriteUrls) { + assertThat(favoriteUrls.size(), equalTo(1)); + assertThat(favoriteUrls.get(0), equalTo("url-0")); + latch.countDown(); + } + }); + latch.await(10, TimeUnit.SECONDS); + } + + @Test + public void testThreeEleRepoOrder() throws InterruptedException { + FavoritesRepository mock = mock(FavoritesRepository.class); + GetFavoritesUseCase uc = useCase(mock); + + // when + { + ArrayList mockList = new ArrayList<>(); + mockList.add(new FavoriteModel(10, "url-0")); + mockList.add(new FavoriteModel(12, "url-2")); + mockList.add(new FavoriteModel(11, "url-1")); + when(mock.getFavorites()).thenReturn(mockList); + } + + final CountDownLatch latch = new CountDownLatch(1); + uc.getFavorites(new GetFavoritesUseCase.Callback() { + @Override + public void favoriteUrlsUpdated(List favoriteUrls) { + assertThat(favoriteUrls.size(), equalTo(3)); + assertThat(favoriteUrls.get(0), equalTo("url-0")); + assertThat(favoriteUrls.get(1), equalTo("url-2")); + assertThat(favoriteUrls.get(2), equalTo("url-1")); + latch.countDown(); + } + }); + latch.await(10, TimeUnit.SECONDS); + } + + private GetFavoritesUseCase useCase(FavoritesRepository repo) { + return new GetFavoritesUseCase(repo); + } +}