Day83 of #100DaysOfCode

Kushagra Kesav
3 min readApr 30, 2022
Day83 of #100DaysOfCode

Hii folks 🙌

Today I will be continuing the same pathway in which we will see the best practices in writing the test case for ViewModel.

Unit 3: Navigation

Pathway 3: Advanced navigation app Examples

https://developer.android.com/courses/android-basics-kotlin/course

Test ViewModels and LiveData

Best practices

The price is updated when the quantity of cupcakes is selected, and when the date is selected. Although both of these should be tested, it’s generally preferable to test only for a single functionality. Therefore, we’ll make separate methods for each test: one function to test the price when the quantity is updated, and a separate function to test the price when the date is updated. We never want the outcome of a test to fail because a different test failed.

  • Create a method called price_twelve_cupcakes() and annotate it as a test.
  • In the method, create an instance of the OrderViewModel and call the setQuantity() method, passing in 12 as a parameter.
val viewModel = OrderViewModel()
viewModel.setQuantity(12)
  • Looking at the PRICE_PER_CUPCAKE in OrderViewModel, we can see that cupcakes are $2.00 each. We can also see that resetOrder() is called every time the ViewModel is initialized, and in this method, the default date is today's date, and PRICE_FOR_SAME_DAY_PICKUP is $3.00. Therefore, 12 * 2 + 3 = 27. We expect the value of the price variable, after selecting 12 cupcakes, to be $27.00. So let's make an assertion that our expected value of $27.00 equals the value of the price LiveData object.
assertEquals("$27.00", viewModel.price.value)

Now run the test.

It should fail!

  • The test result says that our actual value was null. There is an explanation for this. If we look at the price variable in OrderViewModel we will see this:
val price: LiveData<String> = Transformations.map(_price) {
// Format the price into the local currency and return this as LiveData<String>
NumberFormat.getCurrencyInstance().format(it)
}
  • This is an example of why LiveData should be observed in testing. The value of price is set by using a Transformation. Essentially, this code takes the value that we assign to price and transforms it to a currency format so we don't have to do it manually. However, this code has other implications. When transforming a LiveData object, the code doesn't get called unless it absolutely has to be, this saves resources on a mobile device. The code will only be called if we observe the object for changes. Of course, this is done in our app, but we also need to do the same for the test.
  • In our test method, add the following line before setting the quantity:
viewModel.price.observeForever {}
  • Our test should look like this:
@Test
fun price_twelve_cupcakes() {
val viewModel = OrderViewModel()
viewModel.price.observeForever {}
viewModel.setQuantity(12)
assertEquals("$27.00", viewModel.price.value)
}

Now if we run our test it should pass.

That is all for Day83 ✅

Thanks for reading, See you tomorrow!

--

--