Robolectric
The previous two lessons left a gap: plain JUnit unit tests can't touch real Android framework classes, and Espresso needs an actual device or emulator for every run. Robolectric fills that gap — it simulates the Android framework well enough to run code that uses Activity, Context, and View directly on the local JVM, with no device attached at all.
Adding Robolectric
// app/build.gradle
dependencies {
testImplementation 'org.robolectric:robolectric:4.13'
testImplementation 'androidx.test:core:1.6.1'
}
@RunWith(RobolectricTestRunner.class)
Annotating a test class with @RunWith(RobolectricTestRunner.class) tells JUnit to let Robolectric intercept and simulate Android framework calls for every test in that class, instead of running them unmodified on the plain JVM (which would throw "not mocked" errors, as noted in the Unit Testing lesson).
Worked Example: Testing an Activity
This test launches RecipeBox's RecipeDetailActivity with Robolectric and checks that a recipe's title is actually rendered in its TextView — real Activity lifecycle and real view inflation, without a device.
@RunWith(RobolectricTestRunner.class)
public class RecipeDetailActivityTest {
@Test
public void displaysRecipeTitle() {
Intent intent = new Intent(ApplicationProvider.getApplicationContext(), RecipeDetailActivity.class);
intent.putExtra("recipeId", "recipe_42");
RecipeDetailActivity activity = Robolectric.buildActivity(RecipeDetailActivity.class, intent)
.create()
.resume()
.get();
TextView titleView = activity.findViewById(R.id.tvRecipeTitle);
assertEquals("Pancakes", titleView.getText().toString());
}
}
- Robolectric.buildActivity(...) drives the real Activity lifecycle methods (create(), resume(), etc.) exactly as Android would, but simulated on the JVM.
- activity.findViewById(...) works because Robolectric actually inflates the real layout XML — this is not a mock of the view, it's the genuine inflated TextView.
- This runs in a fraction of a second compared to an equivalent Espresso test, since there's no APK install or device boot involved.
Robolectric vs Espresso vs Plain JUnit
| Plain JUnit | Robolectric | Espresso (instrumented) | |
|---|---|---|---|
| Runs on | JVM | JVM (simulated Android) | Real device/emulator |
| Android framework classes | Not available | Simulated | Real |
| Speed | Fastest | Fast | Slowest |
| Best for | Pure logic (validators, mappers) | Activities/Fragments without a real device | Full UI flows, real rendering |
| Confidence level | Logic only | High, but simulated | Highest — the real thing |