Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unit Testing AndroidViewModel classes

Im writting Unit Tests for my app and I've found a "speed bump" while writting them. While testing subclasses of AndroidViewModel im missing the Application parameter for its initialization. I've already read this question that uses Robolectric.

This is what I already tried so far:

  • Using Robolectric as the question describes. As far as I understand, Robolectric can use your custom Application class for testing, the thing is im not using a custom application class as I dont need it. (the app is not that complex).
  • Using mockito. Mockito throws an exception saying that the Context class cannot be mocked.
  • Using the InstrumentationRegistry. I moved the test classes from the test folder to the androidTest folder, giving me access to the androidTestImplementation dependencies, I tried using the InstrumentationRegistry.getContext() and parse it to Application, of course this didn't worked, throwing a cast exception. I felt so dumb trying this but again, it was worth the shot.

I just want to instanciate my AndroidViewModel classes so I can call their public methods, but the Application parameter is needed. What can I do for this?

fun someTest() {
   val testViewModel = MyViewModelThatExtendsFromAndroidViewModel(**missing application parameter**)
   testViewModel.foo() // The code never reaches here as the testViewModel cant be initializated
}
like image 729
Alfredo Bejarano Avatar asked Aug 31 '25 22:08

Alfredo Bejarano


1 Answers

I had the same issue, and found two solutions.

You can use Robolectric in a Unit Test, inside test directory, and choose the platform Application class.

@RunWith(RobolectricTestRunner::class)
@Config(application = Application::class)
class ViewModelTest {

    @Test
    @Throws(Exception::class)
    fun someTest() {
        val application = RuntimeEnvironment.application
        val testViewModel = MyViewModelThatExtendsFromAndroidViewModel(application)
        testViewModel.foo()
    }

}

Or you can use an InstrumentationTest inside androidTest directory, and cast the InstrumentationRegistry.getTargetContext().applicationContext to Application:

@RunWith(AndroidJUnit4::class)
class ViewModelTest {

    @Test
    @Throws(Exception::class)
    fun someTest() {
        val application = ApplicationProvider.getApplicationContext() as Application
        val testViewModel = MyViewModelThatExtendsFromAndroidViewModel(application)
        testViewModel.foo()
    }

}

Hope it helped!

like image 149
Bruno Coelho Avatar answered Sep 03 '25 13:09

Bruno Coelho