Skip to content

Upgrade to Robolectric 4.x

Migrating to 4.15

Deprecations

Deprecated symbol Replacement
org.robolectric:shadows-playservices Use APIs provided by Google Player Services libraries
ActivityController#configurationChange(Configuration, DisplayMetrics, int) ActivityController#configurationChange(Configuration, DisplayMetrics)
AttributeSetBuilder Xml#asAttributeSet()
Config.Builder#setAssetDir() See build system integration
Config.Builder#setLibraries() See build system integration
Config.Builder#setPackageName() See build system integration
Config.Builder#setResourceDir() See build system integration
Robolectric#buildAttributeSet() Robolectric#getAttributeSetFromXml()
Robolectric#flushBackgroundThreadScheduler() ShadowLooper#runToEndOfTasks()
Robolectric#flushForegroundThreadScheduler() ShadowLooper#runToEndOfTasks()
Robolectric#getBackgroundThreadScheduler() This is only needed in the LEGACY looper mode. We strongly encourage you to use the PAUSED looper mode (which is the default)
Robolectric#getForegroundThreadScheduler() This is only needed in the LEGACY looper mode. We strongly encourage you to use the PAUSED looper mode (which is the default)
RuntimeEnvironment#getMasterScheduler() This is only needed in the LEGACY looper mode. We strongly encourage you to use the PAUSED looper mode (which is the default)
RuntimeEnvironment#setMasterScheduler() This is only needed in the LEGACY looper mode. We strongly encourage you to use the PAUSED looper mode (which is the default)
ShadowApplication#runBackgroundTasks() This is only needed in the LEGACY looper mode. We strongly encourage you to use the PAUSED looper mode (which is the default)
ShadowAssetInputStream#isNinePatch() Only use this in LEGACY graphics mode
ShadowRoleManager#addHeldRole() ShadowRoleManager#addRoleHolder()
ShadowRoleManager#addAvailableRole() ShadowRoleManager#addRoleHolder()
ShadowRoleManager#removeAvailableRole() ShadowRoleManager#removeRoleHolder()
ShadowRoleManager#removeHeldRole() ShadowRoleManager#removeRoleHolder()

Removals

Removed symbol Replacement
org.robolectric:shadows-multidex No longer needed with min SDK being 21+
AndroidManifest#supportsBinaryResourcesMode() N/A (it always returned true)
AndroidManifest#supportsLegacyResourcesMode() N/A (it always returned false)
ConfigMerger Provider<Config>
DependencyResolver#getLocalArtifactUrls() N/A (overriding getLocalArtifactUrl() is enough)
Fs#fileFromPath(path) Fs.fromUrl(path)
Fs#newFile(file) file.toPath()
FsFile Path
FsFile#getPath() Fs.externalize(path)
FsFile#join(name) path.resolve(name)
InvokeDynamicClassInstrumentor ClassInstrumentor
IShadow#directlyOn(T, Class<T>) Use a combination of Reflector and Direct
MavenManifestFactory See build system integration
PackageItemData#getClassName() PackageItemData#getName()
ProxyMaker Use a combination of Reflector and Direct
Qualifiers#addScreenWidth() Configuration#screenWidthDp
Qualifiers#addSmallestScreenWidth() Configuration#smallestScreenWidthDp
Qualifiers#getOrientation() Configuration#orientation
Qualifiers#getPlatformVersion() Build.VERSION#SDK_INT
Qualifiers#getScreenWidth() Configuration#screenWidthDp
Qualifiers#getSmallestScreenWidth() Configuration#smallestScreenWidthDp
RoboSettings Read/write the robolectric.scheduling.global system property
Scheduler#idleConstantly() Scheduler#setIdleState()
SdkPicker DefaultSdkPicker
Shadow#directlyOn(T, Class<T>) Use a combination of Reflector and Direct
ShadowApplication#addWakeLock() Use the PowerManager APIs
ShadowApplication#clearWakeLocks() ShadowPowerManager#clearWakeLocks()
ShadowApplication#getAppWidgetManager() Context#getSystemService(Context.APPWIDGET_SERVICE)
ShadowApplication#getBluetoothAdapter() BluetoothAdapter#getDefaultAdapter()
ShadowApplication#getForegroundThreadScheduler() Use the PAUSED looper mode (which is the default)
ShadowApplication#getInstance() ApplicationProvider#getApplicationContext()
ShadowApplication#getLatestWakeLock() ShadowPowerManager#getLatestWakeLock()
ShadowApplication#getSingleton() N/A
ShadowAssetInputStream#getDelegate() N/A
ShadowImpl#directlyOn(T, Class<T>) Use a combination of Reflector and Direct
ShadowMap#convertToShadowName() N/A

Other Changes

  • TestLifecycle no longer has a generic type.
  • Renamed ActivityData#isClearTaskOnLaungh() into ActivityData#isClearTaskOnLaunch().
  • Renamed ResourceIds#makeIdentifer() into ResourceIds#makeIdentifier().

Migrating to 4.14

Deprecations

Deprecated symbol Replacement
org.robolectric:shadows-multidex No longer needed with min SDK being 21+
Implements#looseSignatures() Use either @ClassName or @Implementation(methodName)
Supercedes Supersedes

Removals

Removed symbol Replacement
FragmentTestUtil See Test your fragments

Migrating to 4.13

Breaking Changes

  • This release bumps the min SDK version from 19 to 21, following the move made by the AndroidX ecosystem.

Deprecations

Deprecated symbol Replacement
Scheduler Use LooperMode.PAUSED and ShadowLooper's APIs

Removals

Removed symbol Replacement
Qualifiers#addPlatformVersion() N/A
RuntimeEnvironment#useLegacyResources() N/A (it always returned false)

Migrating to 4.12

Deprecations

Deprecated symbol Replacement
RoboSettings#isUseGlobalScheduler() Use LooperMode.PAUSED
RoboSettings#setUseGlobalScheduler() Use LooperMode.PAUSED

Removals

Removed symbol Replacement
RobolectricTestRunner#getConfig() Provider<Config>
RuntimeEnvironment#setUseLegacyResources() N/A

Migrating to 4.0

Project Configuration

Robolectric 4.0 requires Android Gradle Plugin 3.2 or greater.

Update the configuration in your module's build.gradle/build.gradle.kts file:

android {
  compileSdkVersion 28 // Or newer
  testOptions.unitTests.includeAndroidResources = true
}
android {
  compileSdkVersion = 28 // Or newer
  testOptions.unitTests.isIncludeAndroidResources = true
}

Add the following in your gradle.properties file:

android.enableUnitTestBinaryResources=true

If you have dependencies on com.android.support.test, switch them to androidx.test; see Migrate to AndroidX.

Deprecations

3.8 4.0
ShadowApplication.getInstance() RuntimeEnvironment.application
ShadowApplication.getLatestAlertDialog() ShadowAlertDialog.getLatestAlertDialog()
ShadowApplication.getLatestDialog() ShadowDialog.getLatestDialog()
ShadowApplication.getLatestPopupMenu() ShadowPopupMenu.getLatestPopupMenu()
ShadowLooper.getShadowMainLooper() shadowOf(Looper.getMainLooper())

The automatic migration tool includes a migration to help with this.

The following attributes of the @Config annotation are no longer supported when using binary resources mode:

  • assetDir and resourceDir: follow the recommended file structure of your build system.
  • manifest: Robolectric always uses the merged manifest generated by the Android toolchain. If your test was using a custom manifest you'll need to adapt it to not rely on that.
  • packageName: to change your package name, override the applicationId in your build system.

Improper Use of Shadows

Prior to Robolectric 4.0, it was possible (but ill-advised) to get the shadow for an Android framework object and invoke framework methods there. This could result in unexpected behavior (e.g., code in overridden methods in subclasses wouldn't be called). Shadow implementation methods are now marked protected to guard against this. Always invoke framework methods directly on the Android class.

3.8 4.0
shadowOf(activity).finish(); activity.finish()
ShadowSystemClock.currentTimeMillis(); System.currentTimeMillis()

The automatic migration tool will fix most of these for you.

androidx.test

Robolectric 4.0 includes initial support for androidx.test APIs. We strongly recommend adding the latest version of androidx.test:core as a test dependency and using those APIs whenever possible rather than using Robolectric-specific APIs.

3.8 4.0
RuntimeEnvironment.application ApplicationProvider.getApplicationContext()
ShadowMotionEvent MotionEventBuilder

Troubleshooting

Robolectric 4.0 replaces its old home-grown resource handling code with a direct adaptation of Android's resource handling code, using the full Android toolchain. This greatly improves fidelity to the behavior of a real Android device, but if your tests were relying on the quirks of the old code, you may need to fix your tests.

Some likely issues include:

android.view.InflateException: Binary XML file line #3: Failed to resolve attribute at index 17: TypedValue{t=0x2/d=0x7f01000e a=-1}

This happens when your Activity is using a theme that lacks values for certain attributes used by layouts. Make sure you've specified an appropriate theme for your activities in your AndroidManifest.