Does Robolectric require Java 9?

35,112

Solution 1

on your test class, you need to annotate with @Config with an array of sdk as a parameter.

@Config(sdk = {Build.VERSION_CODES.O_MR1})
class SampleTest {}

for Kotlin

@Config(sdk = [Build.VERSION_CODES.O_MR1])
class SampleTest {}

Your tests should run.

Solution 2

Robolectric 4.3.1 added support for API 29 but... with the following requirement:

Running tests on Android API 29 now strictly requires a Java9 runtime or newer

So if you are targeting API 29 or higher, you have to run your Robolectric using Java9.


Update 28/07/21: Using Java 11 in Android Studio

Android Studio Arctic Fox 2020.3.1 (with AGP 7.0) now bundles JDK 11 and configures Gradle to use it by default.

Ref:

Update 26/08/20: Using Java 9 in Android Studio

Since Android Studio 3.6.0 you can setup JDK9 in the File/Project Structure dialog without problems.

JDK 9

Also, Android Studio will also start using JDK 11 in 4.2 (more info).

Old answer:

Unfortunately, you cannot configure your Android Studio project to use JDK9 yet (as Android Studio 3.5.3): Project structure

But you can change the target JRE to JDK9 from your test run configuration (Run / Edit Configuration): Test run configuration


Keeping Robolectric with Java 8

If you don't want to / cannot use Java 9, there are a couple of workarounds to be able to run your tests using Java 8:

Configure Robolectric to emulate a lower SDK in the whole project:

  1. Create a robolectric.properties file under app/src/test/resources.
  2. In the file add the following like to emulate Android API28:

robolectric.properties

sdk=28

Note: if you have a multi-module project, theoretically you can have a global robolectric.properties in the root directory of your project. But I couldn't make it work... so, unfortunately, I had to duplicate the file for every module, e.g. core/src/test/resources.

Docs: robolectric.properties file

Configure Robolectric to emulate a lower SDK in a specific test:

If you don't want to configure the emulated SDK for the whole project, you can configure it for individual tests using the Robolectric @Config annotation:

@RunWith(AndroidJUnit4::class)
@Config(sdk = [Build.VERSION_CODES.P])
class MyRobolectricTest {...}

Docs: @Config annotation


Why is Java 9 required by Robolectric to support Android Q?

Robolectric uses the AOSP build toolchain to build the Android Framework JARS. For Q, the Java toolchain was updated to use java9, and thus produce java9 bytecode (version 53 class files). Attempting to run Robolectric tests on Q on a java8 SDK would then fail with an error like:

java.lang.UnsupportedClassVersionError: org/xmlpull/v1/XmlPullParser has been compiled by a more recent version of the Java Runtime (class file version 53.0), this version of the Java Runtime only recognizes class file versions up to 52.0

Dx in Android Q was also updated to support version 53 class files. Because Robolectric uses these Framework Jars, there's no way around requiring a Java 9+ JVM. (more info)

Solution 3

Annotate your test with

@Config(sdk = Build.VERSION_CODES.O_MR1)

or sdk = 27. The annotation can go above the class or the test method that's causing the error.

You may still get the warning that Java 9 is required, but the test will run against the supported SDK.

Solution 4

You have to run on Java 9 only when you test against Android Q. Check compatibility section on https://github.com/robolectric/robolectric/releases/tag/robolectric-4.3

Solution 5

//For Kotlin

@Config(sdk = [Build.VERSION_CODES.O_MR1])

@RunWith(RobolectricTestRunner::class)

class MainActivityTest { }

Share:
35,112

Related videos on Youtube

The_Martian
Author by

The_Martian

Android developer, entrepreneur and just curious interested in tensorflow and AR.

Updated on August 12, 2021

Comments

  • The_Martian
    The_Martian almost 3 years

    All the tests are passing, but I get the below warning. Robolectric is telling me that Java 9 is required. I am using the latest version of Robolectric.

    [Robolectric] WARN: Android SDK 10000 requires Java 9 (have Java 8). Tests won't be run on SDK 10000 unless explicitly requested.
    [Robolectric] com.example.testcaseWithRobolectric.MainActivityTest.testAllElements: sdk=28; resources=BINARY
    Called loadFromPath(/system/framework/framework-res.apk, true); mode=binary sdk=28
    

    Process finished with exit code 0

    This is my Gradle:

        dependencies {
            implementation fileTree(dir: 'libs', include: ['*.jar'])
            implementation 'com.android.support:appcompat-v7:28.0.0'
            implementation 'com.android.support.constraint:constraint-layout:1.1.3'
            testImplementation 'junit:junit:4.12'
            androidTestImplementation 'com.android.support.test:runner:1.0.2'
            androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
            implementation project(path: ':domain_layer')
            testImplementation "org.robolectric:robolectric:4.3"
        }
    
    defaultConfig {
            applicationId "com.example.testcaseWithRobolectric"
            minSdkVersion 21
            targetSdkVersion 28
            versionCode 1
            versionName "1.0"
            testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
        }
    
    • Pradeep Sodhi
      Pradeep Sodhi over 4 years
      How you resolved this issue?
  • The_Martian
    The_Martian almost 5 years
    I get the same warning even if I downgrade to 27.
  • Eugen Martynov
    Eugen Martynov almost 5 years
    It is a warning that says that you will have to use Java 9 when you will target Android Q
  • Minas Mina
    Minas Mina about 4 years
    Java versions greater than 9 also work. On Linux it might look like this: /lib/jvm/java-11-openjdk-amd64.
  • Archie G. Quiñones
    Archie G. Quiñones about 4 years
    This should be the selected answer. Specially when sharing unit and instrumentation test, this is a better approach.
  • Jenea Vranceanu
    Jenea Vranceanu about 4 years
    If you want to run your test against all SDK versions your app supports (except SDK 29) the annotation should look a little bit different: @Config(maxSdk = Build.VERSION_CODES.P) Build.VERSION_CODES.P is equal to 28, just in case.
  • ATom
    ATom about 4 years
    This stops working for me when I changed targetSdkVersion to 29. Why? I still want to run test on API 28.
  • Prashant
    Prashant almost 4 years
    For me this changed was needed: @Config(sdk = intArrayOf(Build.VERSION_CODES.O_MR1))
  • Filipe Bezerra de Sousa
    Filipe Bezerra de Sousa over 3 years
    This is the most straightforward answer and also it works. For my use case, I needed just to create the robolectric.properties with sdk=28 inside the app\src\test\resources package and voilà
  • Tonnie
    Tonnie over 3 years
    Used this for Kotlin and worked, @Config(sdk = [Build.VERSION_CODES.P]) thanks lots.