Home Android & Kotlin Books Advanced Android App Architecture

13
Testing MVVM Written by Aldo Olivares

Heads up... You're reading this book for free, with parts of this chapter shown beyond this point as scrambled text.

You can unlock the rest of this book, and our entire catalogue of books and videos, with a raywenderlich.com Professional subscription.

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:

@RunWith(MockitoJUnitRunner::class)
class AddViewModelTest {
  private lateinit var addViewModel: AddViewModel
}
@Mock
lateinit var repository: MovieRepository
//1
@Before
fun setup() {
  //2
  addViewModel = AddViewModel(repository)
}
//1
@Test
fun cantSaveMovieWithoutTitle() {
  //2
  addViewModel.title.set("")
  addViewModel.releaseDate.set("")
  //3
  val canSaveMovie = addViewModel.canSaveMovie()
  //4
  assertEquals(false, canSaveMovie)
}

@Test
fun cantSaveMovieWithoutDate() {
  addViewModel.title.set("Awesome Movie I")
  addViewModel.releaseDate.set("")
  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) {
        finish()
      } 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.

@Test
fun isMovieProperlySaved(){
  addViewModel.title.set("Awesome Movie II")
  addViewModel.releaseDate.set("1994")
  addViewModel.saveMovie()
  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"
@get:Rule
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 scrambled 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.