Posted on

Android Testing pt. 1.3 | Robolectric


android robolectric

Designed by Freepik

 

Today we’re going to get into testing Android apps with Robolectric. This one is quite tricky, so let’s get to it

 

Testing View of MVP

If you followed my previous posts, we learned how to unit test some of our code with Mockito, in particular, Presenter part. Because by itself Presenter is quite modular and easy to instantiate with mocks

Now View holds all the references to layout views, RecyclerView adapters, Presenter etc. You could extract it just like we did with Presenter. So it would look something like that


And then you instantiate it in activity/tests. This might seem like complete overhead. But since by using MVP we already design our app in a completely different way from simple app architecture, it’s just an architecture solution. And now we can unit test our View part with Mockito just like we did with Presenter, right?

Nope, even though I mocked my RecyclerView.Adapter implementation class, I still got a NPE on calling #notifyIitemInserted (parent’s method). Obviously, there’re some bugs with Mockito when extending Android RecyclerView.Adapter

Testing notifying RecyclerView.Adapter is one of the tests for my View, so having a test suite without it would be incomplete. That’s why I recommend testing View with Robolectric

What’s Robolectric

They advertise it as a unit testing framework. It runs locally on your computer and has access to Android framework’s classes. I think it’s just as integrated testing as it is unit one. Because with Robolectric you can instantiate your activity and find views by ids, set their properties, check listeners and more

Which is totally fine, it doesn’t really matter in which category lies those tests, with Robolectric you can test your app completely basically. They run much slower than regular local tests. Initial spin up takes me about 20 – 30 secs, tests themselves take around 200 ms though. So I wouldn’t say that it’s in the TDD kind of area, where you can easily run tests during each method implementations. Still faster than using Espresso which runs on Android device

Code

Let’s get started. First I want to test correct implementations of my ChatContract.View. It handles updating layout with its public methods. And delegates work to Presenter on user events

First, add Robolectric dependency


Since ChatContrat.View is implemented by activity – we can just use this method 


It runs all the initial activity lifecycle methods (onCreate, onStart, onResume…). So the layout is inflated and you can just find views by ids in the test itself. Which is great, this means we don’t need getters for them. We still need setters for activity fields like adapters, array lists, because we’re going to mock them.

Here’s my test suite


 

As you see, I set view properties just in the test itself and then verify correct implementation of my methods by retrieving view properties and checking them. Rather than what we did with Presenter by using Mockito.verify (check that mock’s object method was called)

And views are returned to default state on each test because @Before method is called before each test, meaning layout is being inflated each time. So no need to reset anything

Here’s the View implementations


 

Again, this is more of an integrated testing, but it’s way easier to do it this way than mocking all the activity views and adding setters for them. I still figuring out which way of testing I will prefer

Testing Listeners

And this part I separated because here we’ll test if View called correct methods of Presenter. It happens in view listers and with Robolectric you can easily test that


 

And here’s the implementation


 

Testing listeners might seem unnecessary because it’s just delegation, but it was pretty easy, why not include them as well

Conclusion

Alright, I hope now you understand where Robolectric stands in the testing. It’s a unique tool and feels like instrumented UI tests running locally. You can get the source code here