When utilizing Jetpack Compose alongside Dagger Hilt for dependency management, your application does not recognize your current app module in test cases. To address this issue and facilitate the testing of composable functions when leveraging Dagger Hilt, it becomes necessary to supply a dedicated test module.

When discussing this topic, I intend to create abstract service and repository classes, along with defining the corresponding module.

To begin, I assume that you already possess your repository, service, and module. Following this assumption, I proceed to create a delegated module. Be sure that you impelemented your dependencies:

    implementation("com.google.dagger:hilt-android:2.48")
    implementation("androidx.hilt:hilt-navigation-compose:1.1.0")
    ksp("com.google.dagger:hilt-android-compiler:2.48")
    androidTestImplementation("com.google.dagger:hilt-android-testing:2.48")
    kspTest("com.google.dagger:hilt-android-compiler:2.48")
interface MyService {
    // Your Services
}

class MyRepository @Inject constructor(myService: MyService) {
    // Your Repository
}

@Module
@InstallIn(SingletonComponent::class)
object Module {
    // Set your module here such as sharedPreferences, Room, Retrofit etc..
}


Let’s prepare our UI: 

@AndroidEntryPoint
class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            MyAppTheme {
                MyNavigatipnGraph(rememberNavController())
            }
        }
    }
}

@Composable
fun MyNavigationGraph(
    navHostController: NavHostController
) {
    NavHost(
        navController = navHostController,
        route = Graph.ROOT,
        startDestination = Screens.MyMainScreen.route
    ) {
        authNavGraph(navController = navHostController)
        composable(route = Screens.MyMainScreen.route) {
            MyMainScreen()
        }
    }
}

@Composable
fun MyMainScreen(
    viewModel: MyMainScreenViewModel = hiltViewModel()
) {
    val result by viewModel.resultState.collectAsState()
    Text(
        text = result
    )
}

object Graph {
 ROOT = "ROOT_GRAPH"
}

sealed class Screens(val route: String) {
 data object MyMainScreen: Screens(route = "MY_MAIN_SCREEN") 
}
@HiltViewModel
class MyMainScreenViewModel @Inject constructor(private val myRepository: MyRepository): ViewModel() {
    // your viewModel
    private val _resultState = MutableStateFlow("ui-test-app")
    val resultState = _resultState.asStateFlow()
}


Create a new file named “HiltTestModule”.

@Module
@InstallIn(SingletonComponent::class)
object HiltTestAppModule { 
 // In your app module, you have the option to directly duplicate your original module by copy-pasting. However, in cases where you employ databases such as Realm or Room, it is advisable to utilize the 'inMemory' option directly instead of employing a database for your UI test cases.
}


Subsequently, proceed to create your TestRunner class to facilitate the utilization of your Test Module. Within this function, it is imperative to directly specify ‘HiltTestApplication::class.java.name’ as demonstrated.

class HiltTestRunner: AndroidJUnitRunner() {
    override fun newApplication(cl: ClassLoader?, className: String?, context: Context?): Application {
        return super.newApplication(cl, HiltTestApplication::class.java.name, context)
    }
}


And then, at build.gradle (App Level) file set your testInstrumentationRunner like this:

android {
    defaultConfig {
        testInstrumentationRunner = "yourPackageName.HiltTestRunner"


After completing these steps, we can proceed to create our UI test class and execute our tests as demonstrated below:

@UninstallModules(AppModule::class)
@HiltAndroidTest
class MyMainUiScreenTest {

    @get:Rule(order = 0)
    var hiltRule = HiltAndroidRule(this)

    @get:Rule(order = 1)
    var composeRule = createAndroidComposeRule<MainActivity>()

    @Before
    fun setup() {
        hiltRule.inject()

        composeRule.activity.setContent {
            val navController = rememberNavController()
            MyAppTheme {
                NavHost(
                    navController = navController,
                    startDestination = Screens.MyMainScreen.route,
                    route = Graph.ROOT
                ) {
                    composable(route = Screens.MyMainScreen.route) {
                        MyMainScreen()
                    }
                }
            }
        }
    }

    @Test
    fun uiTextTest() {
        val result = "ui-test-app"
        composeRule.onNodeWithText(result).assertExists()
    }
}


When utilizing your application, it is necessary to uninstall the current modules due to the requirement of employing your test module. This operation can be executed with the @UninstallModules() annotation. Furthermore, it is imperative to define hiltRule to facilitate the automatic execution of injections. The order of rules, denoted by ‘Rule Order’, specifies the sequence in which rules are applied. Rules with a higher value are applied internally