Robolectric is a framework for unit testing Android applications that allows running tests directly on the JVM without an emulator or physical device. It intercepts Android SDK calls and provides shadow objects that emulate the behavior of real components. According to Robolectric Documentation, 2025, shadow objects replace about 15 thousand Android API classes, ensuring test isolation from the platform.
Key Takeaways
Robolectric is an open-source framework created in 2010 to accelerate Android application testing. Instead of running on an emulator or device, Robolectric provides shadow implementations of Android SDK classes that run directly on the Java Virtual Machine (JVM). This allows thousands of tests to run in seconds.
Traditional Android testing requires running the application on an emulator, which takes 3–10 minutes for building the APK, installing, and launching. Robolectric eliminates this step: tests are compiled as regular Java/Kotlin tests and run via JUnit. This provides a feedback loop of seconds instead of minutes.
Robolectric supports all Android versions from API 16 (Android 4.1) up to the latest stable release. For each version, a corresponding set of shadow objects is provided that emulate the behavior of that specific platform version on which the application is being tested.
The Robolectric architecture is based on intercepting calls through classloader replacement. When a test calls an Android SDK method, Robolectric intercepts the call and routes it to a shadow object. A shadow object is a Java class that mimics the real behavior of an Android component but works without the native platform.
Shadow objects implement the key methods of the original Android classes. For example, ShadowTextView mimics methods like getText(), setText(), getCurrentTextColor(), and others. When textView.setText("Hello") is called, the shadow saves the string and returns it when getText() is invoked. This isolates tests from real rendering and system services.
Robolectric supports over 200 shadow classes covering the main Android SDK components: Activity, Fragment, TextView, Button, RecyclerView, WebView, LocationManager, ConnectivityManager, and many others. Shadow objects follow the same inheritance hierarchy as the original Android classes.
Installing Robolectric in a Gradle project requires adding the testImplementation "org.robolectric:robolectric:4.x" dependency. You also need to specify the androidsdk configuration in the build.gradle file and add the android:testInstrumentationRunner permission. No android-test plugin is required to work with Robolectric.
After adding the dependency, you need to configure the directory for the manifest, resources, and assets. Robolectric automatically finds AndroidManifest.xml, but you may need to specify the path manually via the @Config annotation or system properties. For multi-module projects, configuration is set separately for each module.
// build.gradle — Robolectric configuration
android {
testOptions {
unitTests.includeAndroidResources = true
unitTests.all {
systemProperty 'robolectric.dependency.dir',
project.rootDir.absolutePath + '/build/intermediates'
}
}
}
dependencies {
testImplementation 'org.robolectric:robolectric:4.13'
testImplementation 'org.junit.jupiter:junit-jupiter:5.10.0'
}
The @Config annotation allows overriding test parameters: sdk (API version), manifest (path to manifest), qualifiers (screen configuration, language). This is useful for testing application behavior on different Android versions, screen orientations, and localizations.
Robolectric tests are written as regular unit tests with @RunWith(RobolectricTestRunner.class) for JUnit 4 or via RobolectricExtension for JUnit 5. ActivityController manages the Activity lifecycle: create(), start(), resume(), pause(), stop(), destroy(). This allows detailed testing of each state transition.
To test an Activity, use ActivityController, which sequentially goes through the lifecycle stages. Access to the Activity is done via controller.get(). All view components are accessible through findViewById, just like in a real application. Shadow objects allow checking texts, visibility, colors, and other view attributes.
@RunWith(RobolectricTestRunner.class)
@Config(sdk = BuildConfig.SDK_INT)
public class MainActivityTest {
@Test
public void testActivityDisplaysGreeting() {
ActivityController<MainActivity> controller =
Robolectric.buildActivity(MainActivity.class);
controller.create().start().resume();
MainActivity activity = controller.get();
TextView greeting = activity.findViewById(R.id.greeting);
ShadowTextView shadow = Shadows.shadowOf(greeting);
assertEquals("Welcome!", shadow.getText());
}
}
Robolectric intercepts startActivity() calls and allows checking sent intents via ShadowActivity. This makes it possible to test navigation: verify that clicking a button sends an Intent with the correct Action, Data, and Extra parameters.
@Test
public void testNavigationToDetails() {
controller.create().start().resume();
MainActivity activity = controller.get();
activity.findViewById(R.id.detailsButton).performClick();
ShadowActivity shadowActivity = Shadows.shadowOf(activity);
Intent intent = shadowActivity.getNextStartedActivity();
assertEquals(
DetailsActivity.class.getName(),
intent.getComponent().getClassName()
);
}
Robolectric and the emulator solve different tasks. Robolectric is ideal for fast unit tests, checking UI logic, business components, and repositories. The emulator is required for instrumentation tests, integration testing with APIs, testing the camera, sensors, and performance.
| Characteristic | Robolectric | Emulator |
|---|---|---|
| Speed | ~5 sec per 100 tests | ~5 min per 100 tests |
| Launch | No APK build needed | APK build required |
| Real API | Shadow emulation | Native Android SDK |
| Out-of-the-box | JUnit only | Any frameworks |
Robolectric is well suited for testing ViewModel, Repository, and UseCase — components that use the Android SDK but do not require a real UI. ViewModel is tested via a regular JUnit test with RobolectricExtension, while lifecycle components (LiveData, StateFlow) work in the shadow environment without mocks.
Robolectric supports LiveData out of the box: you can subscribe to LiveData in the test, change state through ViewModel, and check the emitted value. For asynchronous operations, InstantTaskExecutorRule or runBlocking for coroutines is used. This eliminates the need to mock architectural components.
@RunWith(RobolectricTestRunner::class)
@Config(sdk = [BuildConfig.SDK_INT])
class ProfileViewModelTest {
private val repository = FakeUserRepository()
private val viewModel = ProfileViewModel(repository)
@Test
fun `loading profile sets state to success`() = runBlocking {
viewModel.loadProfile("user123")
val state = viewModel.profileState.getOrAwaitValue()
Assertions.assertTrue(state is UiState.Success)
}
}
If the standard Robolectric shadow objects do not cover a needed Android SDK class, you can create a custom Shadow. To do this, create a class with the @Implements(ClassName.class) annotation and implement the required methods with @Implementation. Custom shadows are registered via @Config(shadows = [CustomShadow::class]).
Robolectric supports testing ContentProvider via Robolectric.buildContentProvider(). You can check CRUD operations, queries with URI matching, and permission handling. Resources (strings, colors, dimensions) are also accessible through RuntimeEnvironment.application.resources, allowing you to test code that depends on resources.
Transitioning from instrumentation tests to Robolectric requires a change in approach. Instrumentation tests (AndroidJUnit4) check real behavior on the emulator, while Robolectric checks isolated logic in a shadow environment. It is recommended to cover business logic with Robolectric tests and keep instrumentation tests for integration scenarios.
When migrating, you need to: replace AndroidJUnit4 with RobolectricTestRunner, add @Config with the target SDK version, replace ActivityTestRule with ActivityController, and move dependencies from androidTestImplementation to testImplementation. Mocks (MockK, Mockito) work with Robolectric without changes — they are platform-independent.
Robolectric does not support: testing camera (CameraX), NFC, Bluetooth, biometrics, working with real files and native libraries. These scenarios require instrumentation tests on the emulator. Robolectric also does not reproduce real rendering — layout testing is better done via Compose Test Rule or Espresso. However, for checking business logic, navigation, and ViewModel states, Robolectric completely replaces the emulator with 10x faster execution.
Robolectric requires JDK 11 or higher and is compatible with AGP (Android Gradle Plugin) from 7.0 to the latest stable version. The SDK Manager in Robolectric automatically downloads the required Android API versions on first run — this is a one-time operation. For CI servers, it is recommended to preload the SDK via sdkmanager to avoid delays on the first test run. Updating Robolectric to a new version usually does not require changes in test code, only updating the dependency version in build.gradle.
Robolectric is compatible with popular mocking frameworks: MockK for Kotlin and Mockito for Java. Mocks are used for dependency isolation: repositories, API clients, SharedPreferences. The main rule is not to mock Android SDK classes — shadow objects exist for that. Mock only application layers: UseCase, Repository, DataSource, and other business logic components. This combination of shadow objects and mocks provides maximum flexibility with minimal test writing effort.
Frequently Asked Questions
Espresso is an instrumentation framework that runs on an emulator or device. Robolectric is a unit testing framework that runs on the JVM. Espresso tests real behavior, Robolectric tests isolated logic in a shadow environment. They complement each other.
Yes, Robolectric supports Jetpack Compose starting from version 4.8. Compose component tests are executed using ComposeTestRule, similar to the emulator. However, Compose tests on Robolectric do not check real rendering — only the composition logic.
Robolectric supports multi-module projects. Each module is configured separately with its own manifest and resources. For modules without UI components, a library module without the android plugin is sufficient. In large projects with dozens of modules, Robolectric tests for each module run in parallel, providing additional speed gains compared to sequential runs on the emulator.
The resource problem occurs if build.gradle does not have unitTests.includeAndroidResources = true or there is no @Config annotation with the correct path to the manifest. Robolectric uses compiled resources from build/intermediates.
Robolectric tests are debugged like regular Java/Kotlin tests in Android Studio. Breakpoints, step-through debugging, and inspection of shadow objects and their state are available. Logging is enabled via -Drobolectric.logging=debug in VM options.
Summary
We will develop a mobile application turnkey
IT Sectr creates iOS and Android applications for startups and businesses since 2017. We will advise you and propose the best solution.
Read also