Home Android & Kotlin Books Advanced Android App Architecture

Testing MVVM Written by Aldo Olivares

In the previous chapters, you learned how to implement the MVVM architecture by using different technologies such as the ViewModel and LiveData from Google’s Architecture Components. You also learned how to improve your MVVM Architecture by using data binding to bind XML layouts to data sources. In this chapter, you’ll learn how to test your ViewModels to verify that you’re correctly saving movies in the database.

Getting started

Start by opening the starter project for this chapter. This starter project is the same as the final project of the MVVM sample chapter and contains the following packages:

  • data: Contains the Room database components, including the data access objects, movies database, models and RetrofitClient.
  • viewmodel: Contains the ViewModels.
  • view: Contains the Activities and Adapters.

Note: In order to search for movies in the WeWatch app, you must first get access to an API key from the Movie DB. To get your API own key, sign up for an account at www.themoviedb.org. Then, navigate to your account settings on the website, view your settings for the API, and register for a developer API key. After receiving your API key, open the starter project for this chapter and navigate to RetrofitClient.kt. There, you can replace the existing value for API_KEY with your own.

Build and run the app to verify everything is working.

Creating unit tests

WeWatch has three ViewModels:

class AddViewModelTest {
  private lateinit var addViewModel: AddViewModel
lateinit var repository: MovieRepository
fun setup() {
  addViewModel = AddViewModel(repository)
fun cantSaveMovieWithoutTitle() {
  val canSaveMovie = addViewModel.canSaveMovie()
  assertEquals(false, canSaveMovie)

fun cantSaveMovieWithoutDate() {
  addViewModel.title.set("Awesome Movie I")
  val canSaveMovie = addViewModel.canSaveMovie()
  assertEquals(false, canSaveMovie)

fun canSaveMovie(): Boolean {
  val title = this.title.get()
  val releaseDate = this.releaseDate.get()

  if (title != null && releaseDate != null){
    return title.isNotEmpty() && releaseDate.isNotEmpty()
  return false
<string name="title_date_message">You must enter a title and release date</string>
private fun configureLiveDataObservers() {
  viewModel.getSaveLiveData().observe(this, Observer { saved ->
    saved?.let {
      if (saved) {
      } else {
        showMessage(getString(R.string.title_date_message))//Only this line changes

Testing LiveData

There’s only one method left to test on AddViewModel: saveMovie(). Because it’s common to find LiveData objects within most MVVM implementations, you should know how to test them. saveMovie() uses LiveData objects, so it’s perfect for this section.

fun isMovieProperlySaved(){
  addViewModel.title.set("Awesome Movie II")
  assertEquals(true, addViewModel.getSaveLiveData().value)

java.lang.RuntimeException: Method getMainLooper in android.os.Looper not mocked. See http://g.co/androidstudio/not-mocked for details.

at android.os.Looper.getMainLooper(Looper.java)
at androidx.arch.core.executor.DefaultTaskExecutor.postToMainThread
at androidx.lifecycle.LiveData.postValue(LiveData.java:273)
testImplementation "androidx.arch.core:core-testing:2.0.0"
var rule: TestRule = InstantTaskExecutorRule()

Have a technical question? Want to report a bug? You can ask questions and report bugs to the book authors in our official book forum here.

Have feedback to share about the online reading experience? If you have feedback about the UI, UX, highlighting, or other features of our online readers, you can send them to the design team with the form below:

© 2021 Razeware LLC

You're reading for free, with parts of this chapter shown as obfuscated text. Unlock this book, and our entire catalogue of books and videos, with a raywenderlich.com Professional subscription.

Unlock Now

To highlight or take notes, you’ll need to own this book in a subscription or purchased by itself.