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 thesetQuantity()
method, passing in 12 as a parameter.
val viewModel = OrderViewModel()
viewModel.setQuantity(12)
- Looking at the
PRICE_PER_CUPCAKE
inOrderViewModel
, we can see that cupcakes are $2.00 each. We can also see thatresetOrder()
is called every time theViewModel
is initialized, and in this method, the default date is today's date, andPRICE_FOR_SAME_DAY_PICKUP
is $3.00. Therefore, 12 * 2 + 3 = 27. We expect the value of theprice
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 theprice 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 theprice
variable inOrderViewModel
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 ofprice
is set by using aTransformation
. Essentially, this code takes the value that we assign toprice
and transforms it to a currency format so we don't have to do it manually. However, this code has other implications. When transforming aLiveData
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!