title: How to mock repository livedata & ViewModel methods for unit testing
body: <p>What is the proper way to test verify <code>viewModel.getMoviesByReleaseDate()</code> gets a <code>List&lt;DiscoverMovie&gt;</code> when <code>repository.getMoviesByReleaseDate()</code> is called on <code>viewModel.init()</code>.</p>
  
  <p>My method <code>testRepoFetchDataSuccess()</code> doesn't achieve the above mentioned.
  Kindly provide code example if possible as I'm new to unit testing.</p>
  
  <pre><code>public class TMDbRepository {
  
      private static final String TAG = "TMDbRepository";
  
      private static final String RELEASE_DATE_LTE = "2020-02-02";
      private static final String RELEASE_DATE_DESC = "release_date.desc";
      private static final int PAGES_NO = 1;
  
      private final TMDbWebService webService;
  
      @Inject
      public TMDbRepository(TMDbWebService webService) {
          this.webService = webService;
      }
  
      public Single&lt;DiscoverMovieResponse&gt; getMoviesByReleaseDate() {
          return webService
                  .getMoviesByReleaseDate(RELEASE_DATE_LTE, RELEASE_DATE_DESC, PAGES_NO);
      }
  
      public Single&lt;MovieDetails&gt; getMovieDetails(int id) {
          return webService.getMovieDetails(id);
      }
  }
  </code></pre>
  
  <pre><code>public class MasterFragmentViewModel extends ViewModel {
      private static final String TAG = "MasterFragmentViewModel";
  
      private final RxSingleSchedulers rxSingleSchedulers;
      private final TMDbRepository repository;
      private CompositeDisposable disposable;
  
      private final MutableLiveData&lt;List&lt;DiscoverMovie&gt;&gt; movies = new MutableLiveData&lt;&gt;();
      private final MutableLiveData&lt;Boolean&gt; error = new MutableLiveData&lt;&gt;();
      private final MutableLiveData&lt;Boolean&gt; loading = new MutableLiveData&lt;&gt;();
  
      @Inject
      public MasterFragmentViewModel(TMDbRepository repository, RxSingleSchedulers rxSingleSchedulers) {
          this.repository = repository;
          this.rxSingleSchedulers = rxSingleSchedulers;
          disposable = new CompositeDisposable();
      }
  
      public void init() {
          fetchMoviesByReleaseDate();
      }
  
      private void fetchMoviesByReleaseDate() {
          loading.setValue(true);
  
          disposable.add(
                  repository.getMoviesByReleaseDate()
                          .compose(rxSingleSchedulers.applySchedulers())
                          .subscribeWith(new DisposableSingleObserver&lt;DiscoverMovieResponse&gt;() {
                              @Override
                              public void onSuccess(DiscoverMovieResponse discoverMovieResponse) {
                                  error.setValue(false);
                                  movies.setValue(discoverMovieResponse.getMovieList());
                                  loading.setValue(false);
  //                                Log.d(TAG, "onSuccess: " + discoverMovieResponse.getTotalResults());
                              }
  
                              @Override
                              public void onError(Throwable e) {
                                  Log.d(TAG, "onError: " + e);
                                  error.setValue(true);
                                  loading.setValue(false);
                              }
                          })
          );
      }
  
      public LiveData&lt;List&lt;DiscoverMovie&gt;&gt; getMoviesByReleaseDate() {
          return movies;
      }
  
      public LiveData&lt;Boolean&gt; getError() {
          return error;
      }
  
      public LiveData&lt;Boolean&gt; getLoading() {
          return loading;
      }
  
      @Override
      protected void onCleared() {
          super.onCleared();
          disposable.clear();
          Log.d(TAG, "onCleared: disposable cleared!");
      }
  }
  </code></pre>
  
  <pre><code>public class MasterFragmentTest {
  
      @Rule
      public InstantTaskExecutorRule instantExecutorRule = new InstantTaskExecutorRule();
      @Mock
      TMDbRepository repository;
      @Mock
      LifecycleOwner lifecycleOwner;
      @Mock
      Observer&lt;List&lt;DiscoverMovie&gt;&gt; moviesObserver;
      Lifecycle lifecycle;
      private MasterFragmentViewModel viewModel;
  
      @Before
      public void setUp() throws Exception {
          MockitoAnnotations.initMocks(this);
          lifecycle = new LifecycleRegistry(lifecycleOwner);
          viewModel = new MasterFragmentViewModel(repository, RxSingleSchedulers.TEST_SCHEDULER);
          viewModel.getMoviesByReleaseDate().observeForever(moviesObserver);
      }
  
      @Test
      public void testNull() {
          when(repository.getMoviesByReleaseDate()).thenReturn(null);
          assertNotNull(viewModel.getMoviesByReleaseDate());
          assertTrue(viewModel.getMoviesByReleaseDate().hasObservers());
      }
  
      @Test
      public void testRepoFetchDataSuccess() {
          List&lt;DiscoverMovie&gt; mockList = new ArrayList&lt;&gt;();
          DiscoverMovie discoverMovie = Mockito.mock(DiscoverMovie.class);
          mockList.add(discoverMovie);
  
          when(repository.getMoviesByReleaseDate()).thenReturn(Single.just(new DiscoverMovieResponse()));
          viewModel.init();
          verify(moviesObserver).onChanged(mockList);
      }
  
      @After
      public void tearDown() throws Exception {
          repository = null;
          viewModel = null;
      }
  }
  </code></pre>
  
  <p>Test Result:</p>
  
  <pre><code>Argument(s) are different! Wanted:
  moviesObserver.onChanged(
      [Mock for DiscoverMovie, hashCode: 990897274]
  );
  -&gt; at com.sulaz.tmdb.MasterViewModelTest.testRepoFetchDataSuccess(MasterViewModelTest.java:72)
  Actual invocation has different arguments:
  moviesObserver.onChanged(
      null
  );
  -&gt; at androidx.lifecycle.LiveData.considerNotify(LiveData.java:131)
  </code></pre>