New Android architecture components in action: creating a restaurants map application with Room, ViewModel, LiveData and Dagger 2

Part 3: Tests.

Roman Tolmachev
AndroidPub
3 min readNov 26, 2017

--

Part 1: Architecture overview; Room, web server and Repository components. Part 2: ViewModel, View and Dagger.

I bet we all have this experience developing software in a Western movies style: riding as fast as you can, shooting the enemy and trying to look gorgeous at the same time. I do. If stakes aren’t big, it may be acceptable, but as soon as business starts growing, the price of an error rises as well.

As Android developers, how can we be sure that the quality of the code we write is high? That nothing has broken since the last commit? How can we be more productive, focused primarily on code and architecture, still being confident that the QA is there?

On a larger scale, there is a Continuous Integration. We build our working environment in such a way that we divide big tasks into smaller logical pieces, isolate them until we finish and check extensively that they don’t break anything the moment we merge them into the main codebase.

On a smaller scale, there is an automatic testing. We write unit, integration o functional tests, whatever makes sense given the task we work on, and run them.

Combined together, these two approaches help maintain the chaos under control. There is even a movement #qualitymatters, which is a manifesto promoting higher responsibility when it comes to testing and quality assurance of Android apps.

Back to our application, what and how should we test? Let’s start with unit tests. In the application, we have Utils class, which has a method hasConnection(). In order to test it, we’ll use Mockito, and stub the necessary classes:

Mockito.`when` are stubs, something like “when breakfast, then return eggs”. We provide predefined response, or stub, to check the desired behaviour.

What about unit testing of ViewModel, for example? It’s quite straightforward as well. We can mock Observable and stub the response in the same fashion, to verify that the interaction is right.

As was mentioned in the first part, I use standalone Wire Mock web server in the development. In tests, however, I prefer to use lightweight MockWebServer from Square, since WireMock gradle dependency contains extremely large number of methods — 73K, more than 65K dex limit just for one library.

One thing to notice here, is that it is possible to share assets and code between test and androidTest. I use MockWebServer in both kinds of tests, but keep .json stubs only in one folder, test/resources. To do this, modify gradle file like this:

In order to test DAO, we’ll need to use real in-memory Database object. We mock Observer as we did in the ViewModel test and observe changes:

Remember the Restaurants entity class?

The problem here is that it contains nullable fields, and inserting null into DAO will crash the app. Our RestaurantsRepository class filters out invalid fields, and to test it we’ll treat it as a white box, using .json stubs with invalid objects as response from GET Restaurants API request.

Stubbed response with object missing “name” field

timeout() function in Mockito waits for expected result to appear, allowing for asynchronous behaviour.

Finally, UI tests. We have several cases:

  1. wait for map to load, check that all UI elements are present;
  2. wait for map to load, check that it has markers;
  3. wait for map to load, select cuisine via Spinner, check that markers remained belong to that type of cuisine

The easiest way to achieve this (and when it comes to maps, the only one) is by using UiAutomator. It allows us to see the elements we want to test via UiAutomator Viewer, like this:

Each element on the screen is reachable from the tests

That’s it. Check the project at Github to see the whole picture:

--

--