Robolectric has reach a big milestone recently: V3-rc2, so it was time to upgrade all my personal projects.

With the new release, the team has introduced new concepts and new APIs (and removed and renamed others). In most cases, I find the new API and structure much more readable, and generally like it.
But as a long time user of Robolectric, it also means that I have a lot of code to refactor.

Note: all code in this post is Public Domain as described in CC0.

First, to make things clear, if it wasn't worth the hassle, I would not upgrade to v3, but this new version comes with a lot of nice improvements and Robolectric, in general, is awesome beyond words.

Second, let's get to the migration guide:

Gradle stuff

You no longer need the Robolectric Gradle plugin. So just remove classpath 'org.robolectric:robolectric-gradle-plugin' from build.gradle.
Some developers had used a hack to get Robolectric tests navigable in Android Studio: and/or You don't need those anymore.

Any specific Robolectric settings should also be removed, since we are not using the Robolectric Gradle Plugin anymore. Remove this:

With Android Gradle Plugin v1.1.0 there is a built-in support for unit-test (using mockableAndroidJar), so we no longer need to setup Robolectric as androidTestCompile.
Change androidTestCompile('org.robolectric:robolectric:2.4') to testCompile 'org.robolectric:robolectric:3.0-rc2'
DO NOT USE com.squareup:fest-android:1.0.8. If you have it in your testCompile be sure to remove it. There is a conflict between it and Robolectric which causes all Fragment/Activity related unit-tests to fail with NoSuchMethodError.
If you have to use com.squareup:fest-android:1.0.8, then remove support-v4 from it:

TestRunner

You have probably used @RunWith(RobolectricTestRunner.class) in your classes. Switch to RobolectricGradleTestRunner, but also add a @Config annotation, and point to your app's BuildConfig class: This is enough, but I opted to a different approach: a custom test-runner that sets the Robolectric configuration: This test-runner will set the app's SDK level to 21 (since Robolectric does not support anything higher than that, right now), and will set the constants value to the app's BuildConfig class.

API and Behavioral Changes

Entry Points

  • Robolectric.application does not exist anymore. From now on use RuntimeEnvironment.application.
  • Robolectric.shadowOf() does not exist anymore. From now on use Shadows.shadowOf().
  • Robolectric.getShadowApplication() does not exist anymore. From now on use ShadowApplication.getInstance().

Activity life-cycle management

Robolectric lets you manage the life cycle of the activity using it's ActivityController. This is still there, but there are two additions:

  • ActivityController.postCreate() was added.
  • ActivityController now has a new setup method which is a shorthand for create().start().postCreate(null).resume().visible().get().
  • and another shorthand was added Robolectric.setupActivity(Class<T extends Activity>).

Quite useful.

Add-On Modules

Robolectric was broken up to modules; the main library will only include Shadows for the main Android framework classes, and anything else (support library, maps, etc) is served as an Add-On Module.
I don't have much to say about that, other than: if you want a Shadow of a class that is part of an external library (for example, support-v4's LocalBroadcastManager), be sure to include the right Add-On (for example testCompile 'org.robolectric:shadows-support-v4'). You can access the Shadow using the Add-On's specific Shadows entry-point (for completeness: org.robolectric.support.v4.Shadows).

Missing stuff

This is what I've found so far:

  • IntentFilter will not do equals correctly anymore. I guess that this is due to some cleanup, which resulted in Shadows to be removed. I used a new static method to calculate match: I use Mockito a lot and needed a Matcher too.

Replaced stuff

This is what I've found so far:

  • TestCursor was replaced with RoboCursor, which is an improved version of it. This is a great addition.
  • UI Thread is now called ForegroundScheduler, which means that Robolectric.runUiThreadTasksIncludingDelayedTasks() is now called Robolectric.flushForegroundScheduler();

Other

This is what I've found so far:

  • Time now respects the default time-zone! So make sure you set it correctly in your unit-tests (most probably in the @Before method): Also, note that Time is Deprecated with API-22, so you might want to refactor to use GregorianCalendar. But, no pressure.
  • Robolectric now supports API level 21! This means that if you assumed in your tests that you are running on an API level 18 (which was the highest/default API level for Robolectric v2.4), this is no longer the case! The default API level is 21!
    @Config(emulateSdk = 18) or @Config(qualifiers = "v19") are your best friends there. And don't forget to add the missing unit-test for API levels higher than that.
  • Since the robolectric gradle closure is removed, any special Java related configuration (e.g., maxHeapSize) should be moved to android->testOptions->unitTests.all closure. Something like this:


Please share your tips and tricks for migrating in the comments! I'll update this post as things coming in


blog comments powered by Disqus