45

When will Robolectric be compatible with Android SDK 29? Did I upgraded too early by changing targetSdkVersion and compileSdkVersion to 29?

When I run my unit tests I get this huge stacktrace:

java.lang.IllegalArgumentException: API level 29 is not available

    at org.robolectric.plugins.UnknownSdk.getJarPath(UnknownSdk.java:25)
    at
org.robolectric.internal.AndroidSandbox$SdkSandboxClassLoader.<init>(AndroidSandbox.java:102)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native
Method)     at
sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
    at
sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
    at org.robolectric.util.inject.Injector.inject(Injector.java:239)   at
org.robolectric.util.inject.Injector.lambda$memoized$1(Injector.java:221)
    at
org.robolectric.util.inject.Injector$MemoizingProvider.get(Injector.java:485)
    at
org.robolectric.util.inject.Injector.getInstanceInternal(Injector.java:213)
    at
org.robolectric.util.inject.Injector.resolveDependencies(Injector.java:283)
    at org.robolectric.util.inject.Injector.inject(Injector.java:237)   at
org.robolectric.util.inject.Injector.lambda$memoized$1(Injector.java:221)
    at
org.robolectric.util.inject.Injector$MemoizingProvider.get(Injector.java:485)
    at
org.robolectric.util.inject.Injector.getInstanceInternal(Injector.java:213)
    at
org.robolectric.util.inject.Injector.getInstance(Injector.java:197)
    at org.robolectric.util.inject.Injector.access$700(Injector.java:85)
    at
org.robolectric.util.inject.Injector$ScopeBuilderProvider.create(Injector.java:551)
    at
org.robolectric.util.inject.Injector$ScopeBuilderProvider.lambda$get$0(Injector.java:534)
    at com.sun.proxy.$Proxy13.build(Unknown Source)     at
org.robolectric.internal.SandboxManager.getAndroidSandbox(SandboxManager.java:57)
    at
org.robolectric.RobolectricTestRunner.getSandbox(RobolectricTestRunner.java:267)
    at
org.robolectric.RobolectricTestRunner.getSandbox(RobolectricTestRunner.java:63)
    at
org.robolectric.internal.SandboxTestRunner$2.evaluate(SandboxTestRunner.java:215)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)    at
org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
    at
org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)  at
org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)     at
org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)   at
org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)     at
org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)    at
org.robolectric.internal.SandboxTestRunner$1.evaluate(SandboxTestRunner.java:96)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)    at
org.junit.runner.JUnitCore.run(JUnitCore.java:137)  at
org.junit.runner.JUnitCore.run(JUnitCore.java:115)  at
org.junit.vintage.engine.execution.RunnerExecutor.execute(RunnerExecutor.java:40)
    at
java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:184)
    at
java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193)
    at java.util.Iterator.forEachRemaining(Iterator.java:116)   at
java.util.Spliterators$IteratorSpliterator.forEachRemaining(Spliterators.java:1801)
    at
java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481)
    at
java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
    at
java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:151)
    at
java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:174)
    at
java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
    at
java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:418)
    at
org.junit.vintage.engine.VintageTestEngine.executeAllChildren(VintageTestEngine.java:80)
    at
org.junit.vintage.engine.VintageTestEngine.execute(VintageTestEngine.java:71)
    at
org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:229)
    at
org.junit.platform.launcher.core.DefaultLauncher.lambda$execute$6(DefaultLauncher.java:197)
    at
org.junit.platform.launcher.core.DefaultLauncher.withInterceptedStreams(DefaultLauncher.java:211)
    at
org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:191)
    at
org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:128)
    at
com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:74)
    at
com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
    at
com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
    at
com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
double-beep
  • 5,031
  • 17
  • 33
  • 41
Bencri
  • 1,173
  • 1
  • 7
  • 22

4 Answers4

72

Create a robolectric.properties file inside the app/src/test/resources directory with the following line:

sdk=28

This will force Robolectric to use API 28 instead of 29.

farmerbb
  • 1,150
  • 8
  • 7
  • Hi, I don't have the "test/resource" directory inside "src", in android studio I choose Project option instead of Android and I have the following folders: androidTest, debug, main, release, test[unitTest]. – Notron Jul 18 '22 at 18:21
21

With Robolectric 4.3.1 we can use the following alternatives:

  1. Run our test with Java 9 or newer. (We can edit the JRE in the run test configuration) enter image description here

If we like to run our test with Java 8, we can:

  1. Annotate our test class with @Config in order to emulate a lower SDK (as mentioned by @bencri and @julio-mendoza).

Like this:

@RunWith(AndroidJUnit4::class)
@Config(sdk = Build.VERSION_CODES.P)
class LoginRobolectricTest {
//...
}
  1. Or, as mentioned by @farmerbb, add the robolectric.properties file inside the app/src/test/resources folder with the SDK we like to run, by example:

sdk=28

enter image description here

Gurunath Sripad
  • 1,308
  • 2
  • 14
  • 24
JuanMoreno
  • 2,498
  • 1
  • 25
  • 34
  • 2
    Adding robolectric.properties worked best. Was easy and worked like a charm. – portfoliobuilder Dec 03 '19 at 18:22
  • 1
    This doesn't work for me. It doesn't seem to be reading the properties file. Any idea why? On Android Studio 4.0 now and it is still failing. – Randy Jun 04 '20 at 17:26
  • What is the purpose of using `Java 9` with Robolectric? – IgorGanapolsky Sep 09 '21 at 16:00
  • @IgorGanapolsky in the release https://github.com/robolectric/robolectric/releases/tag/robolectric-4.3.1 says this: Running tests on Android API 29 now strictly requires a Java9 runtime or newer. If you are seeing errors about unsupported Java version when running tests on API 29 via Android Studio; you can use the 'JRE' field in the Run Configuration dialog to configure a newer Java runtime. See https://developer.android.com/studio/run/rundebugconfig for more background. – JuanMoreno Sep 09 '21 at 17:51
  • Interesting, as of today Robolectric runs on API `30`, but not `31`... – IgorGanapolsky Sep 09 '21 at 18:39
  • @IgorGanapolsky, yeah, also if you see the Robolectric's CI run against Java 11.0.8 https://github.com/robolectric/robolectric/blob/ca9ddc9b4d0cf4ff8a9f19b0e7505b8a10571621/.github/workflows/tests.yml#L29 – JuanMoreno Sep 09 '21 at 20:10
9

If anyone is wondering, the solution for me was to annotate my test classes with

@Config(sdk = Build.VERSION_CODES.O_MR1)
Bencri
  • 1,173
  • 1
  • 7
  • 22
4

Latest Robolectric 4.3 already supports Android Q (https://github.com/robolectric/robolectric/releases)

Eugen Martynov
  • 19,888
  • 10
  • 61
  • 114