Robolectric (https://github.com/robolectric/robolectric 6,051 ) (MIT, org.robolectric:robolectric:4.17) runs Android code in an ordinary JVM test. It loads a real Android framework jar (android-all-instrumented, 213 MB for Android 16, fetched on first use) through a class loader that rewrites it, and replaces what needs a device with shadow classes. The tests of Compose UI Tests and Navigation Tests run on it: @RunWith(AndroidJUnit4::class) picks Robolectric under src/test and the device runner under src/androidTest. BookNest's first run failed before any test started:
CartScreenTest > classMethod FAILED
java.lang.UnsupportedOperationException: Failed to create a Robolectric sandbox: Android
SDK 36
requires Java 21 (have Java 17)Robolectric simulates the app's targetSdk, and 4.17 needs Java 21 for SDK 36 and 37, while AGP 9.4 runs on JDK 17. Instead of pinning tests to an older SDK with @Config(sdk = [35]), give only the test JVM Java 21 through a Gradle 19,597 toolchain. The next run hit Java's module walls (cannot access class jdk.internal.access.SharedSecrets), which one flag fixed:
tasks.withType<Test>().configureEach {
javaLauncher = javaToolchains.launcherFor { // 5.34.5 Robolectric's SDK 36 needs Java 21
languageVersion = JavaLanguageVersion.of(21)
}
jvmArgs("--add-opens=java.base/jdk.internal.access=ALL-UNNAMED") // for RobolectricWith unitTests.isIncludeAndroidResources = true in testOptions for the merged manifest, all 11 JVM tests passed. The report shows where the time goes: the first Robolectric test in a class took 10.4 seconds to build the sandbox, the next 0.44, and plain JVM tests 0.02-0.17. Leave to a device what Robolectric fakes: real rendering, performance and system dialogs.