Android Unit Testing and why you shouldn’t do it ;)

Malcolm Maima
4 min readMar 23, 2022

Yes, this is clickbait, tests are very important (^o^). If you’re like me who’s never written a test for any of my personal projects, then this article is for you. We’re going to go over the basics of how to write unit tests for Android apps and why this is important for your growth as a developer.

I often hear developers reiterate that if the piece of code you’re writing works then why should I test it? it works right!? While this is true it may not always be the case. As your codebase grows and evolves, certain bits of code may break and you may need to fix them before you can continue. This is where unit testing comes in. As you continually build on top of your codebase, you’ll notice certain breaking changes. Now you see if you have tests in place then you can make sure that you’re not breaking your codebase as some of these tests may fail. This is not magic, you’re going to write code that breaks your codebase at some point if you haven’t already.

There are different types of tests that you can write for your Android apps. These include:

  • Unit tests
  • Integration tests
  • End to end tests
  • UI tests
  • Performance tests
  • Functional tests
  • Smoke tests
  • Regression tests
  • Load tests

Different libraries apply for different types of tests. Some common testing libraries include/but not limited to:

  • Mockito
  • JUnit
  • Espresso
  • LoadView
  • Robolectric
  • MockWebServer

For the purposes of this article, we will be using JUnit as our testing suite. Now if you’ve worked with MVVM before, then concepts such as ViewModels and LiveData are not new to you. If they are, I highly recommend going through this article/series link

The basic concept when it comes to Views and ViewModels is that you have a View and a ViewModel. The ViewModel is responsible for handling the logic of the View. The View is responsible for displaying the data from the ViewModel.

Traditional architectures such as MVC used a different approach to this in that it consists of three key components:
- Model: The data that is being displayed
- View: The UI that displays the data
- Controller: The logic that handles the data and the UI

We’re not going to go into the nitty-gritty details of how it compares to MVVM in this article.

Back to testing. If the ViewModel is responsible for handling the logic of the View, then how do you test it? Android comes bundled with JUnit.

Say we have an app that has a ProfileActivity.kt and a ProfileViewModel.kt Within this activity we are able to see some basic information about the user like username, email address, profile photo. We can test this by creating a test class and a test method. A simple neat trick I use to generate test classes in android studio is going into the kotlin file and pressing CTRL + SHIFT + T. This should generate a test class for you with prebuilt test methods.

Now we should have a ProfileViewModelTest.kt file. Our Profile View model has a getUser() method that returns a LiveData object of type UserResponse.

Our getUser() makes an asynchronous call to our repository using Kotlin coroutines which is responsible for providing a clean API for accessing data. What that means is that the repository can gather data from different data sources(different REST APIs, cache, local database storage) and it provides this data to the rest of the app. In our case, our repository is responsible for providing data from our backend [backend]

Since we expect a response of type UserResponse when we call getUser() we can test this by mocking the response as you can see in the code above (line 46–52). Now to explain what is happening in the test.

  • We declare the repository as a lateinit var. This means that we can’t initialize it until we have a context.
  • we declare the viewModel as a lateinit var

after this you can see an annotation @get:Rule which is a JUnit rule that allows us to run a test in a separate process. This is useful for testing asynchronous code.

  • We declare instantiationException and coroutineRule. These two are used to run the test in a coroutine context.

You can read more on JUnit annotations [here]

After declaring the lateinit vars we can now initialize the repository and viewModel. We initialize our repository with mock. Now comes our actual test. You’ll notice the @Test annotation. This is a JUnit annotation that tells JUnit that this is a test method. In our getUser() method we
create a testUserResponse object and set sample data to it. We then call the getUser() method and assert that the response is equal to the testUserResponse.

How is this helpful? This means that if our UserResponse object is changed in the backend, we can test our app to make sure that our app is still working as expected. Pretty neat right!?

I hope this article convinces you to write more tests and why they are important in the development cycle of your app. To view more tests and how to go about testing you can check out our github repo [here]

I am eager to hear your feedback and comments especially if you’re new to writing tests in android.

References

  • MVVM architecture, ViewModel and LiveData (link)
  • Getting started with writing functional test cases in Android (link)
  • Simple Kotlin smoke-tests (Retrofit, JUnit, and bug-free production) (link)
  • Regression Testing in Mobile Development (link)
  • Fundamentals of testing Android apps (link)
  • JUnit 5 tutorial — Learn how to write unit tests (link)
  • Testing your Android ViewModel — with examples (link)
  • Unit Testing for ViewModel (link)

--

--

Malcolm Maima

Android Engineer @ Equity Bank — I code stuff…I eat a lot too, coffee makes me sleepy Love cartoons and robots. http://linktr.ee/malcolmmaima