Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to test AndroidViewModel in unit test

I'm trying to test ViewModel(AndroidViewModel parent), in unit tests(test folder) but when using

val application = ApplicationProvider.getApplicationContext<Application>()

it gives me this error

java.lang.IllegalStateException: No instrumentation registered! Must run under a registering instrumentation.

ExampleUnitTest

class ExampleUnitTest {
    private lateinit var myAndroidViewModel: MyAndroidViewModel
    private val app = ApplicationProvider.getApplicationContext<Application>()

    @Before
    fun init() {
        myAndroidViewModel = MyAndroidViewModel(app)
    }

    @Test
    fun addition_isCorrect() {
        assertEquals(4, 2 + 2)
    }
}

build.gradle

android {
    testOptions {
        unitTests.returnDefaultValues = true
    }
}
dependencies {
    testImplementation 'junit:junit:4.12'
    testImplementation 'androidx.test:core-ktx:1.3.0'
}

If I use robolectric, I no longer get said error, but I don't feel that it is a good option, since robolectric is more for ui test.

I hope you can help me. Thanks.

like image 936
Woz Avatar asked Oct 18 '25 13:10

Woz


2 Answers

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 = MyAndroidViewModel(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 = MyAndroidViewModel(application)
        testViewModel.foo()
    }

}

Hope it helped!

like image 79
Ulagapandi UPMS Avatar answered Oct 20 '25 03:10

Ulagapandi UPMS


For Unit testing, one may want to use @ActivityScoped and then @Inject the constructor ...


But for testing ViewModel I'd rather use androidx.hilt:hilt-lifecycle-viewmodel:

dependencies {
  implementation 'androidx.hilt:hilt-lifecycle-viewmodel:1.0.0-alpha01'

  // When using Kotlin.
  kapt 'androidx.hilt:hilt-compiler:1.0.0-alpha01'

  // When using Java.
  annotationProcessor 'androidx.hilt:hilt-compiler:1.0.0-alpha01'
}

Then one can @ViewModelInject:

class ExampleViewModel @ViewModelInject constructor(
  private val repository: ExampleRepository,
  @Assisted private val savedStateHandle: SavedStateHandle
) : ViewModel() {
  ...
}

See Hilt and Jetpack integrations.


Here's another one example using Hilt with MockK, which it's author summarizes as:

Testing with Hilt, just @UninstallModules and then @BindValue.

like image 30
Martin Zeitler Avatar answered Oct 20 '25 04:10

Martin Zeitler



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!