Set Up Android Jetpack Compose Instrumentation Test with Hilt
A step-by-step guide to set up the Android Jetpack Compose UI test with Hilt dependency injection
Testing is a crucial part of Android development, and based on my experience, setting up instrumentation tests can be challenging — especially when using Hilt for dependency injection.
In this article, I will guide you through the setup process, ensuring your Compose UI tests run smoothly with Hilt. I will be using my app, “TrendNow”, for the sample. You can see the series here TrendNow: Build an Android News App with Jetpack Compose.
1. Set up the test dependencies
I’m using the Gradle version catalog to manage the app dependencies, you can read more about it here Migrate your build to version catalogs.
# inside libs.versions.toml
[versions]
composeBom = "2025.03.00"
espressoCore = "3.6.1"
junit = "4.13.2"
hilt = "2.55"
[libraries]
androidx-compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "composeBom" }
# junit4 version managed by compose bom
androidx-ui-test-junit4 = { group = "androidx.compose.ui", name = "ui-test-junit4" }
androidx-espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espressoCore" }
junit = { group = "junit", name = "junit", version.ref = "junit" }
hilt-test = { group = "com.google.dagger", name = "hilt-android-testing", version.ref = "hilt" }
hilt-ksp = { group = "com.google.dagger", name = "hilt-android-compiler", version.ref = "hilt" }The dependencies above are required, add them to the app build.gradle.kts.
...
dependencies {
...
androidTestImplementation(libs.androidx.junit)
androidTestImplementation(libs.androidx.espresso.core)
androidTestImplementation(platform(libs.androidx.compose.bom))
androidTestImplementation(libs.androidx.ui.test.junit4)
androidTestImplementation(libs.hilt.test)
kspAndroidTest(libs.hilt.ksp)
}Once done, “Sync Project with Gradle Files” to install the dependencies.
2. Configure Hilt for instrumentation test
Next, we need to configure the Test Runner and Activity for Hilt.
Set up the Hilt test runner
Create a custom runner inside the androidTest directory.
import dagger.hilt.android.testing.HiltTestApplication
class HiltTestRunner : AndroidJUnitRunner() {
override fun newApplication(cl: ClassLoader?, name: String?, context: Context?): Application {
return super.newApplication(
cl,
HiltTestApplication::class.java.name,
context
)
}
}- Use
HiltTestApplicationclass that comes from this dependencyhilt-test = { group = “com.google.dagger”, name = “hilt-android-testing” }
Then register the runner to testInstrumentationRunner inside the app build.gradle.kts file.
android {
...
defaultConfig {
applicationId = "com.trend.now"
minSdk = 24
targetSdk = 35
...
// make sure to set the package name and class name correctly
testInstrumentationRunner = "com.trend.now.HiltTestRunner"
}
...
}Set up the Hilt test activity
Creating a Hilt test activity is required to make sure the dependency injection to Android components (a class that has annotation @AndroidEntryPoint) is working.
Get Dani Mahardhika’s stories in your inbox
Join Medium for free to get updates from this writer.
Why not just use the actual Activity? Because the actual Activity usually contains complex navigation which makes testing a specific screen harder. Unless the test involves screen navigation, it’s recommended to create a dedicated activity for the test.
abstract class BaseActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
...
}
...
}
@AndroidEntryPoint
class MainActivity : BaseActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// set the activity content and navigation
setContent {
TrendNowTheme {
AppNavigation()
}
}
}
}- Create an
abstract class BaseActivityand move the original activity behavior except for the app content, navigation, and@AndroidEntryPointannotation. - Create another Activity that extends the
BaseActivitywith@AndroidEntryPointannotation that sets the app content and navigation.
Then create the Hilt test activity inside the debug directory.
@AndroidEntryPoint
class HiltTestActivity : BaseActivity()- Extend the
BaseActivityso that the Hilt test activity inherits the original activity behavior.
Notes:
- Creating a base activity that contains the original activity behavior is optional, you can use an empty activity if it’s enough.
- Move the required behavior or code only to the base activity instead of moving all of them. Why? To exclude unrelated behavior with the UI test requirements.
Then create AndroidManifest.xml file inside the debug directory and register the Hilt test activity.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:tools="http://schemas.android.com/tools"
xmlns:android="http://schemas.android.com/apk/res/android">
<application tools:ignore="MissingApplicationIcon">
<activity
android:name="com.trend.now.HiltTestActivity"
android:exported="false">
</activity>
</application>
</manifest>- No need to add
android.intent.action.MAINandandroid.intent.category.LAUNCHER.
3. Write a UI test in a Hilt-enabled Android Compose app
After the steps above are done, then we can write our UI test.
@HiltAndroidTest
@RunWith(AndroidJUnit4::class)
class NewsScreenTest {
@get:Rule
var hiltRule = HiltAndroidRule(this)
@get:Rule
val composeTestRule = createAndroidComposeRule<HiltTestActivity>()
@Test
fun shouldShowAppTitleOnTheTopAppBar() {
// when
composeTestRule.setContent {
// set the screen that you want to test here
TrendNowTheme {
NewsScreen(navController = rememberNavController())
}
}
// then
composeTestRule.onNodeWithText("TrendNow").assertIsDisplayed()
}
}- Make sure to add
@HiltAndroidTestannotation to the test class to enable Hilt dependency injection within the test environment. HiltAndroidRuleis required to initialize Hilt and ensure the Hilt dependencies are injected before the test starts.onNodeWithText()is used to find a component with specific text.assertIsDisplayed()is used to make sure the component found (above) is visible to the user.
Now that you’ve set up Hilt for Jetpack Compose tests, you have a solid foundation for writing reliable UI tests. See the official documentation for more info Hilt testing. Happy testing! 🎯
Troubleshooting
How to use a custom application for the test?
Using the default HiltTestApplication mostly is enough, but if it still does not satisfy your needs, we can create a custom Hilt test application.
Similar to the Hilt test activity, we can create an abstract class to include the original app behavior.
abstract class BaseApplication : Application() {
override fun onCreate() {
super.onCreate()
...
}
...
}
@HiltAndroidApp
class NewsApplication : BaseApplication()- Create an
abstract class BaseApplicationand move the original application behavior except for the@HiltAndroidAppannotation. - Create another Application that extends the
BaseApplicationwith@HiltAndroidAppannotation.
Then we can create the custom Hilt test application inside the androidTest directory.
import dagger.hilt.android.testing.CustomTestApplication
@CustomTestApplication(BaseApplication::class)
interface HiltTestApplication- You can use a different name for the interface name, I’m using
HiltTestApplicationhere. - Make sure to pass the
abstract class BaseApplicationcreated above to the@CustomTestApplication.
Then rebuild the project using Build → Rebuild Project or using this gradle command,
./gradlew clean assembleDebugAndroidTestAfter that the HiltTestApplication_Application class will be generated inside the build directory like the image below,
- The generated file name format should be
InterfaceName_Application.
Then register the generated class to the HiltTestRunner class.
class HiltTestRunner : AndroidJUnitRunner() {
override fun newApplication(cl: ClassLoader?, name: String?, context: Context?): Application {
return super.newApplication(
cl,
// register here
HiltTestApplication_Application::class.java.name,
context
)
}
}- Replace the default
HiltTestApplicationwith the custom Application.
How to solve an error “Unable to resolve activity for: Intent…”?
Unable to resolve activity for: Intent {
act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER]
cmp=com.your.package.test/com.your.package.HiltTestActivity }If you get any error related to the Hilt test activity or Hit test application, make sure,
- Both of
HiltTestActivityandAndroidManifest.xmlare placed inside thedebugdirectory, notandroidTestdirectory. - The Hilt test application is placed inside the
androidTestdirectory, no need to declare it in theAndroidManifest.xml.









