Originally published on my blog.
Import dependencies
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.
Create a simple User class
data class User(val id: Int)
Create a ViewModel
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 helper function to mock classes with types (generics)
Create a kotlin file - MockitoUtils.kt inside your test folder.
inline fun <reified T> mock(): T = Mockito.mock(T::class.java)
Creating the unit test
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.
Top comments (1)
Thank you 🙏