In order to save resources and execution time, I'm trying to migrate my Compose tests to the unitTest
module so they can run without instrumentation on the JVM.
However, ehen I run my Compose tests, I get the following error:
Failed to instantiate test runner class androidx.test.internal.runner.junit4.AndroidJUnit4ClassRunner
I did some research, and I should be doing everything correctly, so I'm confused why it's not working. I even tried the suggestion here, but that didn't fix it either. Below is my code.
MyScreenTest
import .junit.Rule
import .junit.Test
import .junit.runner.RunWith
@RunWith(AndroidJUnit4::class)
class MyScreenTest {
// ...
@get:Rule
val composeTestRule = createComposeRule()
@Test
fun testSomething() {
composeTestRule.run {
// ...
}
}
}
build.gradle.kts
android {
// ...
defaultConfig {
// ...
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}
buildFeatures {
compose = true
}
composeOptions {
kotlinCompilerExtensionVersion = "1.5.3"
}
testOptions {
unitTests {
isIncludeAndroidResources = true
}
}
}
dependencies {
// ...
testImplementation(libs.androidx.junit)
testImplementation(libspose.ui.test.junit4)
testImplementation(libs.mockk)
testImplementation(libs.junit)
testImplementation(libs.androidx.runner)
debugImplementation(libs.androidx.ui.test.manifest)
}
libs.versions.toml
[versions]
agp = "8.6.1"
kotlin = "1.9.10"
coreKtx = "1.15.0"
junit = "4.13.2"
junitVersion = "1.2.1"
espressoCore = "3.6.1"
appcompat = "1.7.0"
material = "1.12.0"
constraintlayout = "2.2.1"
navigationFragmentKtx = "2.8.8"
navigationUiKtx = "2.8.8"
retrofit = "2.9.0"
activityCompose = "1.10.1"
composeBom = "2025.02.00"
composeNavigation = "2.8.8"
kotlinxSerilization = "1.6.3"
mockk = "1.13.8"
kotlinxCoroutinesTest = "1.7.3"
jetbrainsKotlinJvm = "1.9.10"
composeTest = "1.7.8"
runner = "1.6.2"
[libraries]
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
junit = { group = "junit", name = "junit", version.ref = "junit" }
androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" }
androidx-espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espressoCore" }
androidx-appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "appcompat" }
material = { group = "com.google.android.material", name = "material", version.ref = "material" }
androidx-constraintlayout = { group = "androidx.constraintlayout", name = "constraintlayout", version.ref = "constraintlayout" }
androidx-navigation-fragment-ktx = { group = "androidx.navigation", name = "navigation-fragment-ktx", version.ref = "navigationFragmentKtx" }
androidx-navigation-ui-ktx = { group = "androidx.navigation", name = "navigation-ui-ktx", version.ref = "navigationUiKtx" }
retrofit = { module = "com.squareup.retrofit2:retrofit", version.ref = "retrofit" }
converter-gson = { module = "com.squareup.retrofit2:converter-gson", version.ref = "retrofit" }
androidx-activity-compose = { group = "androidx.activity", name = "activity-compose", version.ref = "activityCompose" }
androidx-compose-bom = { group = "androidxpose", name = "compose-bom", version.ref = "composeBom" }
androidx-compose-material3 = { group = "androidxpose.material3", name = "material3" }
navigation-compose = { module = "androidx.navigation:navigation-compose", version.ref = "composeNavigation"}
kotlinx-serialization-json = { module = ".jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "kotlinxSerilization"}
mockk = { module = "io.mockk:mockk", version.ref = "mockk" }
kotlinx-coroutines-test = { module = ".jetbrains.kotlinx:kotlinx-coroutines-test", version.ref = "kotlinxCoroutinesTest" }
compose-ui-test-junit4 = { module = "androidxpose.ui:ui-test-junit4", version.ref = "composeTest" }
androidx-ui-test-manifest = { module = "androidxpose.ui:ui-test-manifest", version.ref = "composeTest" }
androidx-runner = { module = "androidx.test:runner", version.ref = "runner" }
[plugins]
// ...