Source code can be found here.
implementation 'androidx.lifecycle:lifecycle-extensions:2.0.0'
testImplementation 'androidx.arch.core:core-testing:2.0.1'
testImplementation 'org.mockito:mockito-core:2.28.2'
Check the official Android documentation for the latest version of these Android packages.
For Mockito, check out their Github repository for the latest version.
data class User(val id: Int)
class MainViewModel : ViewModel() {
private val _user = MutableLiveData<User>()
val user: LiveData<User>
get() = _user
fun fetchUser(id: Int) {
val user = User(id)
_user.value = user
}
}
Create a kotlin file - MockitoUtils.kt inside your test folder.
inline fun <reified T> mock(): T = Mockito.mock(T::class.java)
class MainViewModelTest {
@get:Rule
val rule = InstantTaskExecutorRule()
private lateinit var viewModel: MainViewModel
private val observer: Observer<User> = mock()
@Before
fun before() {
viewModel = MainViewModel()
viewModel.user.observeForever(observer)
}
@Test
fun fetchUser_ShouldReturnUser() {
val expectedUser = User(1)
viewModel.fetchUser(expectedUser.id)
val captor = ArgumentCaptor.forClass(User::class.java)
captor.run {
verify(observer, times(1)).onChanged(capture())
assertEquals(expectedUser, value)
}
}
}
@get:Rule
val rule = InstantTaskExecutorRule()
What this rule basically does is allow us to run LiveData synchronously. This rule is from the core-testing package that was imported earlier.
private val observer: Observer<User> = mock()
The helper function that we made will help us be able to mock our Observer. Try mocking it the standard way and you’ll see what I mean - mock(Observer<User>::class.java)
.
val captor = ArgumentCaptor.forClass(User::class.java)
captor.run {
verify(observer, times(1)).onChanged(capture())
assertEquals(expectedUser, value)
}
ArgumentCaptor does what the class name is called - capture argument(s). We capture()
the argument when the onChanged(...)
method of our Observer is called.
Adding verify(observer, times(1)).onChanged(capture())
allows you to capture instances where the LiveData is called multiple times when you expect it to be called only once.
Assert that the expectedUser that we’ve created is equal to the emitted user of our LiveData.
Lastly, run the goddamn test.
If you’ve found this helpful, subscribe to my newsletter below to be updated with the latest posts and get a free book on the 7 ways to become a really good Android developer!👇
Do You Want to Become Really Good at Android Development?
Here are 7 ways to do it👇