'Real ViewModel with Composable Injected by Hilt in Instrumentation Test Zero Argument Constructor

I want to have the real ViewModel injected into my composable. This question's answer is stating how to mock the injected view model which is not what I want.

My composable is receiving the view model like this:

fun YourDetailsScreen(viewModel: YourDetailsViewModel = viewModel()) {

The viewModel() method is the inline function provided by the androidx.lifecycle.viewmodel.compose package.

As far as I'm aware, I have implemented the custom test runner, my instrumentation test is configured correctly with the @HiltAndroidTest and the HiltAndroidRule wrapping my composeTestRule like so:

@get:Rule
val rule: RuleChain = RuleChain.outerRule(hiltAndroidRule)
   .around(composeTestRule)

When I launch my composable, I get the following exception:

Caused by: java.lang.InstantiationException: java.lang.Class<com.zzz.feature.onboarding.registration.yourdetails.YourDetailsViewModel> has no zero argument constructor

Here is my ViewModel's constructor.

@HiltViewModel
class YourDetailsViewModel @Inject constructor(
    private val isFirstNameValidUseCase: IsFirstNameValidUseCase,
    private val isLastNameValidUseCase: IsLastNameValidUseCase,
    private val isPhoneNumberValidUseCase: IsPhoneNumberValidUseCase
) : ViewModel()

Everything is injected fine when running the app, I just can't get it to work in my android tests!



Solution 1:[1]

After some hours of debugging, found the issue.

Basically, the main problem was that I was using createComposeRule() instead of createAndroidComposeRule<MyActivity>(), so the HiltViewModelFactory was not used.

After I started using createAndroidComposeRule<MyActivity>() as follow, my test started running:

@RunWith(AndroidJUnit4::class)
@HiltAndroidTest
class MyScreenTest  {

    val hiltRule = HiltAndroidRule(this)

    val composeTestRule = createAndroidComposeRule<MyActivity>()

    @get:Rule
    val rule: RuleChain = RuleChain.outerRule(hiltRule)
        .around(composeTestRule)

    // Tests....
}

(MyActivity must be annotated with @AndroidEntryPoint)

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 amp