Unit Tests with Mockito and Jacoco in The Main Android Architectures — MVC, MVP, MVVM, Clean, MVI, VIPER, VIPER — part 3: MVP
MVP
If you have some doubts about this architecture, check my other article.
Model
This layer is entirely testable, but It was already done when we tested an MVC project. I was following an incremental methodology. So, I won’t repeat myself. Here I will just refer to my previous article.
View
The view layer definitely is not the proposal for this kind of test. That assertion is valid for all architectures. I would recommend you again read about Espresso.
Presenter
Success Cases
Setup
RX
RxJavaPlugins.setIoSchedulerHandler { Schedulers.trampoline() } RxAndroidPlugins.setInitMainThreadSchedulerHandler { Schedulers.trampoline() }
We had to make changes on our main and io threads to move both to the same work queue. It would be handled as a synchronous job.
Instantiating
view = mock(PersonView::class.java)
model = PersonModel()
presenter = PersonPresenter(view, model)
Here I created a real instance of my model. But pay attention: It was possible in my case because my model is not real. Otherwise, If it would be a real API Rest, we should not make our test depends on an internet connection.
To surround this problem, you could mock our model and its response. You will see it working on failed tests.
Another great approach would be to work with local .json or XML files exactly as your API provides, but for now, this won’t be included in this article sequence.
Here I had to create a mock instance of View, to validate what our presenter will pass to it.
For sure, I must not mock our presenter, because do not make sense to submit a not real instance of what we wish to test.
onFetchPersonSuccess
given: our assumed scenario
//given
setupSuccess()
when: action that we wish to validate its consequences
//when
presenter.fetchPerson()
then: assertion about that consequences
//then val captor = ArgumentCaptor.forClass(String::class.java) inOrder(view)
verify(view, times(1)).showLoading()
verify(view, times(1)).hideLoading()
verify(view, times(1)).showPersonName(captureString(captor)) Assert.assertEquals(captor.value, “hello”)
We are basically validating here a sequence and quantity of interactions that happen to our view, and then we checked which argument that was passed to the method showPersonName
Failure Cases
Setup
Here, We did almost the same. But since, as I told you, our services are not a real API Rest implementation. It always returns a valid response. So, at moment we have to mock our model layer to provide an error instead of success.
onFetchPersonFail
//given
setupFail() `when`(model.providePerson()).thenReturn(Single.error(Throwable()))//when
presenter.fetchPerson()//then
inOrder(view)
verify(view, times(1)).showLoading()
verify(view, times(1)).hideLoading()
verify(view, times(1)).showPersonNameError()
Here, We did almost the same again. But since our model layer now is mocked, It is able only to return the default response like a null. We have to tell Mockito what you wish to return.
Cancel Cases
Setup
Since we expect to check how our application behaves when we cancel a pending request, we can not keep handling it as a synchronous process.
About our layers instances creation, again we have to mock a model layer. Because we wish to do force a delay. I don't want our service to be completed before I have a chance to cancel it.
fetchPersonCancel
Our release method returns true if there is really a request to be canceled.
So, basically, we created a delayed response.
Our assertion checks interactions and if we effectively cancel a request.
Now, let’s see which report can this implementation produce.
Generating Test Results Report
./gradlew app:testMvp_UnitTest
Output
app/build/reports/tests/testMvp_UnitTest/index.html
I hid some tests on our explanation to make it easy, but you can check the whole code on GitHub.
Generating Coverage Report
./gradlew app:testMvp_UnitTestCoverage
Output
app/build/reports/jacoco/testMvp_UnitTestCoverage/index.html
You can check this project on GitHub. Remember to select the architecture that you wish to study on the build variants:
Unit Tests with Mockito and Jacoco in The Main Android Architectures — part 2: MVC
Unit Tests with Mockito and Jacoco in The Main Android Architectures — part 3: MVP
Unit Tests with Mockito and Jacoco in The Main Android Architectures — part 4: MVVM
Unit Tests with Mockito and Jacoco in The Main Android Architectures — part 5: VIPER
Unit Tests with Mockito and Jacoco in The Main Android Architectures — part 6: MVI
Unit Tests with Mockito and Jacoco in The Main Android Architectures — part 7: Clean