Невозможно проверить метод вызова метода из RxJava Subscriber

Я пытаюсь установить тестовый презентатор в своем приложении для Android. Метод, который я пытаюсь проверить, выглядит следующим образом:

@Override public boolean loadNextPage() { if (!mIsLoading) { mIsLoading = true; if (mViewReference.get() != null) { mViewReference.get().showProgress(); } mService.search(mSearchQuery, ++mCurrentPage) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(itemsPage -> { mIsLoading = false; mTotalPages = itemsPage.getPagination().getTotalPages(); if (mViewReference.get() != null) { mViewReference.get().showMovies(itemsPage.getItems()); } }, error -> { mIsLoading = false; Log.d(LOG_TAG, error.toString()); }); } return mTotalPages == 0 || mCurrentPage < mTotalPages; } 

mService – это интерфейс Retrofit, а mService.search() возвращает RxJava Observable<SearchResults> . Мой тестовый код выглядит следующим образом:

 package mobi.zona.presenters; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.runners.MockitoJUnitRunner; import java.util.ArrayList; import java.util.List; import com.example.api.Service; import com.example.model.Movie; import com.example.model.SearchResults; import com.example.views.MoviesListView; import rx.Observable; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @RunWith(MockitoJUnitRunner.class) public class SearchPresenterTest { @Mock Service mService; @Mock MoviesListView mMoviesListView; @Test public void testLoadNextPage() throws Exception { String searchQuery = "the hunger games"; SearchResults searchResults = new SearchResults(); List<Movie> movies = new ArrayList<>(); searchResults.setItems(movies); when(mService.search(searchQuery, 1)).thenReturn(Observable.just(new SearchResults())); MoviesListPresenter presenter = new SearchPresenter(mZonaService, mMoviesListView, searchQuery); presenter.loadNextPage(); verify(mService, times(1)).search(searchQuery, 1); verify(mMoviesListView, times(1)).showProgress(); verify(mMoviesListView, times(1)).showMovies(movies); } } 

Проблема заключается в третьей verify(mMoviesListView, times(1)).showMovies(movies); Line – он всегда терпит неудачу. Whem Я пытаюсь отладить этот тест, я вижу, что поток управления никогда не входит в .subscribe(itemPage - {... Я думаю, что это связано с тем, что я подписываюсь на поток Schedulers.io() , но Не знаю, как это исправить. Любые идеи? EDIT 1: Изменил презентатор, чтобы использовать параметры Scheduler качестве конструктора. Измененный тест выглядит следующим образом:

 @Test public void testLoadNextPage() throws Exception { String searchQuery = "the hunger games"; SearchResults searchResults = new SearchResults(); List<Movie> movies = new ArrayList<>(); searchResults.setItems(movies); when(mZonaService.search(searchQuery, 1)).thenReturn(Observable.just(new SearchResults())); MoviesListPresenter presenter = new SearchPresenter(mZonaService, mMoviesListView, searchQuery, Schedulers.test(), Schedulers.test()); presenter.loadNextPage(); verify(mZonaService, times(1)).search(searchQuery, 1); verify(mMoviesListView, times(1)).showProgress(); verify(mMoviesListView, times(1)).showMovies(movies); } 

Все еще получение этого сообщения об ошибке:

 Wanted but not invoked: mMoviesListView.showMovies([]); -> at com.example.presenters.SearchPresenterTest.testLoadNextPage(SearchPresenterTest.java:46) However, there were other interactions with this mock: mMoviesListView.showProgress(); -> at com.example.presenters.SearchPresenter.loadNextPage(SearchPresenter.java:41) 

В моих приложениях интеракторы / примеры использования / модель ( mService в вашем случае) отвечают за указание Scheduler на операцию (поскольку он лучше знает, какую операцию он выполняет).

Итак, переместите ваш subscribeOn в mService . После этого ваш макет будет работать нормально.

Идя глубже, если теперь вы захотите проверить mService я бы порекомендовал вам сделать его «зависимым» от Scheduler . Другими словами – добавьте Sheduler в качестве параметра конструктора.

 public class MyService { private final Scheduler taskScheduler; public MyService(Scheduler taskScheduler) { this.taskScheduler = taskScheduler; } // ... public Observable<Something> query() { return someObservable.subscribeOn(taskScheduler); } } 

Затем в тестах вы можете использовать Schedulers.immediate() и для реального приложения Schedulers.io() (или как вам нравится, действительно).

Intereting Posts