Preamble
Mockito is a framework that supports creating unit tests using mock objects.
A mock is an object that has properties of the real object while ignoring the hassle of creating a real object.
The reason we should use mock object to perform unit test:
- No need to initialize as real objects so will not be dependent on real objects in the application
- Unit tests will be faster
- The code also looks better
Unit test with Mockito
Suppose we have 1 MovieViewModel as follows:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 | public final class GenreV extends BaseViewModel { private MovieRepository movieRepository; private boolean isExhaust; private int currentPage; private MutableLiveData<ListMovieResponse> mutableLiveData = new MutableLiveData<>(); public boolean isExhaust() { return isExhaust; } public void setExhaust(boolean isExhaust) { this.isExhaust = isExhaust; } public int getCurrentPage() { return currentPage; } public void setCurrentPage(int currentPage) { this.currentPage = currentPage; } public void getMovies(@NotNull String key, int page, int typeLoad) { currentPage = typeLoad == 1 ? page + 1 : page; movieRepository.getMovieByType(key, currentPage) .doOnSubscribe((new Consumer<Disposable>() { @Override public void accept(Disposable disposable) throws Exception { getLoadingLiveData().postValue(true); } })) .doOnTerminate((Action) (new Action() { public final void run() { getLoadingLiveData().postValue(false); } })).subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Consumer<ListMovieResponse>() { @Override public void accept(ListMovieResponse listMovieResponse) throws Exception { mutableLiveData.postValue(listMovieResponse); setExhaust(listMovieResponse.getPage() == listMovieResponse.getTotalPage()); setCurrentPage(listMovieResponse.getPage()); } }); } @NotNull public MutableLiveData getMoviesLiveData() { return mutableLiveData; } public @interface TypeLoad { int LOAD_MORE = 1; int LOAD_NEW = 0; } } |
Now that we need to write the unit test for the getMovies () method, the steps are as follows:
Add Mockito dependence
To add Mockito dependence, we need to add the following line in build.gradle (app)
1 2 | testImplementation 'org.mockito:mockito-core:1.10.19' |
Create a Mock class to perform unit tests
Create a class named MovieViewModelUnitTest in the test package
(Note there are 2 test directories, “androidTest” and “test”, “androidTest” is for us to run the test on the real device and “test” is for us to run the test without the device. Here we create in package “test”)
1 2 3 4 5 | @RunWith(PowerMockRunner.class) public class MovieViewModelUnitTest { } |
Analyze the object to be tested
Here we need to test the getMovies () method of MovieViewModel, in this method we are using MovieRepository, MutableLiveData so we need to mock these 2 objects to use
1 2 3 4 5 6 7 8 9 | @RunWith(PowerMockRunner.class) public class MovieViewModelUnitTest { @Mock private MovieRepository movieRepository; @Mock private MutableLiveData<ListMoviveResponse> mutableLiveData; } |
Use mock objects to define methods
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | @RunWith(PowerMockRunner.class) public class MovieViewModelUnitTest { @Mock private MovieRepository movieRepository; @Mock private MutableLiveData<ListMoviveResponse> mutableLiveData; @Spy private MovieViewModel viewModel = new MovieViewModel(movieRepository); @Before public void before() { viewModel.setRepository(movieRepository); viewModel.setMutableLiveData(mutableLiveData); } @Test public void getMovies() { ListMovieResponse response = new ListMovieResponse(); response.setTotalPage(1); Mockito.when(movieRepository.getMovies(Arguments.anyString(), Arguments.anyInt())).thenReturn(Single.just(response)); viewModel.getMovies("A", 1, 1); Mockito.verify(mutableLiveData).postValue(response); } } |
Above, I gave you a rough guide on how to use Mockito to perform unit tests. Of course there are still many other situations that you have to handle a little more complicated but generally Mockito is quite easy to use because basically still have to pass through the 3 steps above. To find out more, refer here