So I want to test my jetpack compose project. It's easy enough running an instrument test following [these instructions]1 on android dev site, but when you add @HiltViewModel
injection into the combination things get complicated.
I'm trying to test a pretty simple compose screen with a ViewModel that has an @Inject constructor. The screen itself looks like this:
@Composable
fun LandingScreen() {
val loginViewModel: LoginViewModel = viewModel()
MyTheme {
Surface(color = MaterialTheme.colors.background) {
val user by loginViewModel.user.observeAsState()
if (user != null) {
MainScreen()
} else {
LoginScreen(loginViewModel)
}
}
}
}
and this is the view model:
@HiltViewModel
class LoginViewModel @Inject constructor(private val userService: UserService) : ViewModel() {
val user = userService.loggedInUser.asLiveData()
}
User service is of course backed by a room database and the loggedInUser property returns a Flow
.
Things work as expected on standard run but when trying to run it in an instrument test it can't inject the view model.
@HiltAndroidTest
class LandingScreenTest {
@get:Rule
var hiltRule = HiltAndroidRule(this)
@get:Rule
val composeTestRule = createComposeRule()
@Inject
lateinit var loginViewModel: LoginViewModel
@Before
fun init() {
hiltRule.inject()
}
@Test
fun MyTest() {
composeTestRule.setContent {
MyTheme {
LandingScreen()
}
}
composeTestRule.onNodeWithText("Welcome").assertIsDisplayed()
}
}
Injection of an @HiltViewModel class is prohibited since it does not create a ViewModel instance correctly. Access the ViewModel via the Android APIs (e.g. ViewModelProvider) instead. Injected ViewModel: com.example.viewmodels.LoginViewModel
How do you make that work with the ViewModelProvider instead of the @HiltViewModel?