I am trying to test my ViewModel class. I believe that I need to use a HiltViewModelTest
annotation but, Android Studio cannot find the file..
import androidx.test.ext.junit.rules.ActivityScenarioRule
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.elnimijogames.porschegarage.MainActivity
import com.elnimijogames.porschegarage.model.MenuItemRepository
import com.elnimijogames.porschegarage.model.MenuPhotoGalleryRepository
import dagger.hilt.android.testing.BindValue
import dagger.hilt.android.testing.HiltAndroidRule
import dagger.hilt.android.testing.HiltAndroidTest
import org.junit.Assert.assertEquals
import org.junit.Before
import org.junit.Rule
import org.junit.runner.RunWith
import javax.inject.Inject
@HiltAndroidTest
@RunWith(AndroidJUnit4::class)
class MainMenuViewModelTest {
@get:Rule
var hiltRule = HiltAndroidRule(this)
@get:Rule
var activityScenarioRule = ActivityScenarioRule(MainActivity::class.java)
@Inject
lateinit var galleryRepository: MenuPhotoGalleryRepository
@Inject
lateinit var menuItemRepository: MenuItemRepository
@BindValue
@JvmField
val galleryRepositoryBindValue: MenuPhotoGalleryRepository = galleryRepository
@BindValue
@JvmField
val menuItemRepositoryBindValue: MenuItemRepository = menuItemRepository
@Before
fun setup() {
hiltRule.inject()
}
@HiltViewModelTest
fun testMainMenuViewModel() {
val viewModel = MainMenuViewModel(galleryRepository, menuItemRepository)
val expectedGalleryList = galleryRepository.getImageGalleryList()
val expectedMenuList = menuItemRepository.getMenuItemsList()
assertEquals(expectedGalleryList, viewModel.photoGalleryState.value)
assertEquals(expectedMenuList, viewModel.itemMenuState.value)
}
}
If I remove the annotation I instead get the following error when running the test:
MenuPhotoGallery is bound multiple times
MenuItemRepository is bound multiple times
I can't see any specific dependency that I should be using that I'm not already using.
Below is the code for my ViewModel:
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.mutableStateOf
import androidx.lifecycle.ViewModel
import com.elnimijogames.porschegarage.model.MenuItem
import com.elnimijogames.porschegarage.model.MenuItemRepository
import com.elnimijogames.porschegarage.model.MenuPhotoGalleryRepository
import dagger.hilt.android.lifecycle.HiltViewModel
import javax.inject.Inject
@HiltViewModel
class MainMenuViewModel @Inject constructor(
galleryRepository: MenuPhotoGalleryRepository,
menuItemRepository: MenuItemRepository
) : ViewModel() {
val photoGalleryState: MutableState<List<String>> = mutableStateOf(emptyList())
val itemMenuState: MutableState<List<MenuItem>> = mutableStateOf(emptyList())
init {
photoGalleryState.value = galleryRepository.getImageGalleryList()
itemMenuState.value = menuItemRepository.getMenuItemsList()
}
}
My module class looks like this:
@Module
@InstallIn(ViewModelComponent::class)
class AppModule {
@Provides
fun providesMenuPhotoGalleryRepository(): MenuPhotoGalleryRepository = MenuPhotoGalleryRepository()
@Provides
fun providesMenuItemListInterface(): MenuItemListInterface = MenuItemListLocal()
@Provides
fun providesMenuItemListLocal(): MenuItemListLocal = MenuItemListLocal()
@Provides
fun providesMenuItemRepository(menuItemListLocal: MenuItemListLocal): MenuItemRepository = MenuItemRepository(menuItemListLocal)
}
The MenuPhotoGalleryRepository
and MenuItemrepository
files are basic classes with no Hilt annotations.
These are the dependencies in my build.gradle file.
implementation 'androidx.core:core-ktx:1.10.1'
implementation 'androidx.activity:activity-compose:1.7.2'
implementation platform('org.jetbrains.kotlin:kotlin-bom:1.8.0')
implementation platform('androidx.compose:compose-bom:2022.10.00')
implementation 'androidx.compose.ui:ui'
implementation 'androidx.compose.ui:ui-graphics'
implementation 'androidx.compose.ui:ui-tooling-preview'
implementation 'androidx.compose.material3:material3'
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.6.1'
implementation 'androidx.lifecycle:lifecycle-viewmodel-compose:2.6.1'
implementation 'com.google.code.gson:gson:2.10.1'
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
implementation 'androidx.navigation:navigation-compose:2.6.0'
implementation 'io.coil-kt:coil-compose:2.4.0'
// Hilt
implementation 'com.google.dagger:hilt-android:2.46.1'
kapt 'com.google.dagger:hilt-android-compiler:2.46.1'
implementation("androidx.hilt:hilt-work:1.0.0")
kapt("androidx.hilt:hilt-compiler:1.0.0")
implementation("androidx.work:work-runtime-ktx:2.8.1")
implementation("androidx.hilt:hilt-navigation-compose:1.0.0")
// For instrumentation tests
androidTestImplementation 'com.google.dagger:hilt-android-testing:2.46.1'
kaptAndroidTest 'com.google.dagger:hilt-compiler:2.46.1'
// For local unit tests
testImplementation 'com.google.dagger:hilt-android-testing:2.46.1'
kaptTest 'com.google.dagger:hilt-compiler:2.46.1'
Any help is greatly appreciated.