/* * Copyright (C) 2017 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.example.github.repository; import com.android.example.github.api.GithubService; import com.android.example.github.api.RepoSearchResponse; import com.android.example.github.db.GithubDb; import com.android.example.github.db.RepoDao; import com.android.example.github.util.TestUtil; import com.android.example.github.vo.Repo; import com.android.example.github.vo.RepoSearchResult; import com.android.example.github.vo.Resource; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; import android.arch.core.executor.testing.InstantTaskExecutorRule; import android.arch.lifecycle.LiveData; import android.arch.lifecycle.Observer; import java.io.IOException; import java.util.Collections; import java.util.List; import okhttp3.Headers; import okhttp3.MediaType; import okhttp3.ResponseBody; import retrofit2.Call; import retrofit2.Response; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.when; @RunWith(JUnit4.class) public class FetchNextSearchPageTaskTest { @Rule public InstantTaskExecutorRule instantTaskExecutorRule = new InstantTaskExecutorRule(); private GithubService service; private GithubDb db; private RepoDao repoDao; private FetchNextSearchPageTask task; private LiveData<Resource<Boolean>> value; private Observer<Resource<Boolean>> observer; @Before public void init() { service = mock(GithubService.class); db = mock(GithubDb.class); repoDao = mock(RepoDao.class); when(db.repoDao()).thenReturn(repoDao); task = new FetchNextSearchPageTask("foo", service, db); //noinspection unchecked observer = mock(Observer.class); task.getLiveData().observeForever(observer); } @Test public void withoutResult() { when(repoDao.search("foo")).thenReturn(null); task.run(); verify(observer).onChanged(null); verifyNoMoreInteractions(observer); verifyNoMoreInteractions(service); } @Test public void noNextPage() { createDbResult(null); task.run(); verify(observer).onChanged(Resource.success(false)); verifyNoMoreInteractions(observer); verifyNoMoreInteractions(service); } @Test public void nextPageWithNull() throws IOException { createDbResult(1); RepoSearchResponse result = new RepoSearchResponse(); result.setTotal(10); List<Repo> repos = TestUtil.createRepos(10, "a", "b", "c"); result.setItems(repos); Call<RepoSearchResponse> call = createCall(result, null); when(service.searchRepos("foo", 1)).thenReturn(call); task.run(); verify(repoDao).insertRepos(repos); verify(observer).onChanged(Resource.success(false)); } @Test public void nextPageWithMore() throws IOException { createDbResult(1); RepoSearchResponse result = new RepoSearchResponse(); result.setTotal(10); List<Repo> repos = TestUtil.createRepos(10, "a", "b", "c"); result.setItems(repos); result.setNextPage(2); Call<RepoSearchResponse> call = createCall(result, 2); when(service.searchRepos("foo", 1)).thenReturn(call); task.run(); verify(repoDao).insertRepos(repos); verify(observer).onChanged(Resource.success(true)); } @Test public void nextPageApiError() throws IOException { createDbResult(1); Call<RepoSearchResponse> call = mock(Call.class); when(call.execute()).thenReturn(Response.error(400, ResponseBody.create( MediaType.parse("txt"), "bar"))); when(service.searchRepos("foo", 1)).thenReturn(call); task.run(); verify(observer).onChanged(Resource.error("bar", true)); } @Test public void nextPageIOError() throws IOException { createDbResult(1); Call<RepoSearchResponse> call = mock(Call.class); when(call.execute()).thenThrow(new IOException("bar")); when(service.searchRepos("foo", 1)).thenReturn(call); task.run(); verify(observer).onChanged(Resource.error("bar", true)); } private void createDbResult(Integer nextPage) { RepoSearchResult result = new RepoSearchResult("foo", Collections.emptyList(), 0, nextPage); when(repoDao.findSearchResult("foo")).thenReturn(result); } private Call<RepoSearchResponse> createCall(RepoSearchResponse body, Integer nextPage) throws IOException { Headers headers = nextPage == null ? null : Headers .of("link", "<https://api.github.com/search/repositories?q=foo&page=" + nextPage + ">; rel=\"next\""); Response<RepoSearchResponse> success = headers == null ? Response.success(body) : Response.success(body, headers); Call call = mock(Call.class); when(call.execute()).thenReturn(success); //noinspection unchecked return call; } }