Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AndroidViewModel and Unit Tests

I am using AndroidViewModel with LiveData to send Intents to a IntentService and receiving events from an EventBus. I need the Application Context for the Intents and the EventBus.

What is the best way to test AndroidViewModel classes with local tests? I can get it to start with Robolectrics RuntimeEnvironment.application but there doesnt seem to be a shadowOf() for AndroidViewModel to check if the right Intents were sent to the correct receiver.

Perhaps it is somehow possible to do this with Mockito using my own mock-intents and inject them into my AndroidViewModel, but that doesn't seem to be very straightforward.

My code looks something like this:

class UserViewModel(private val app: Application) : AndroidViewModel(app){
val user = MutableLiveData<String>()

...

private fun startGetUserService() {
    val intent = Intent(app, MyIntentService::class.java)
    intent.putExtra(...)
    app.startService(intent)
}

@Subscribe
fun handleSuccess(event: UserCallback.Success) {
    user.value = event.user
}
}

Robolectric Test:

@RunWith(RobolectricTestRunner.class)
public class Test {
@Test
public void testUser() {
    UserViewModel model = new UserViewModel(RuntimeEnvironment.application)
    // how do I test that startGetUserService() is sending
    // the Intent to MyIntentService and check the extras?
}
like image 259
user1892364 Avatar asked Feb 04 '23 23:02

user1892364


1 Answers

I would rather create a mock of your Application class because then it could be used to verify which methods were called on it and which object were passed to those methods. So, it could be like this (in Kotlin):

@RunWith(RobolectricTestRunner::class)
class Test {
    @Test
    public void testUser() { 
        val applicationMock = Mockito.mock(Application::class.java)
        val model = new UserViewModel(applicationMock)
        model.somePublicMethod();

        // this will capture your intent object 
        val intentCaptor = ArgumentCaptor.forClass(Intent::class.java)
        // verify startService is called and capture the argument
        Mockito.verify(applicationMock, times(1)).startService(intentCaptor.capture())

        // extract the argument value
        val intent = intentCaptor.value
        Assert.assertEquals(<your expected string>, intent.getStringExtra(<your key>))
    }
}
like image 70
Anatolii Avatar answered Mar 03 '23 10:03

Anatolii