Chapters

Hide chapters

Advanced Android App Architecture

First Edition · Android 9 · Kotlin 1.3 · Android Studio 3.2

Before You Begin

Section 0: 3 chapters
Show chapters Hide chapters

13. Testing MVVM
Written by Aldo Olivares

Heads up... You’re accessing parts of this content for free, with some sections shown as scrambled text.

Heads up... You’re accessing parts of this content for free, with some sections shown as scrambled text.

Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.

Unlock now

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.
© 2024 Kodeco Inc.

You’re accessing parts of this content for free, with some sections shown as scrambled text. Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.

Unlock now