Robolectric 和 Android SDK 29
Robolectric and Android SDK 29
Robolectric 何时与 Android SDK 29 兼容?我把 targetSdkVersion
和 compileSdkVersion
改成 29 是不是升级得太早了?
当我 运行 我的单元测试时,我得到这个巨大的堆栈跟踪:
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(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(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.access0(Injector.java:85)
at
org.robolectric.util.inject.Injector$ScopeBuilderProvider.create(Injector.java:551)
at
org.robolectric.util.inject.Injector$ScopeBuilderProvider.lambda$get[=12=](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.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.run(ParentRunner.java:290) at
org.junit.runners.ParentRunner.schedule(ParentRunner.java:71) at
org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) at
org.junit.runners.ParentRunner.access[=12=]0(ParentRunner.java:58) at
org.junit.runners.ParentRunner.evaluate(ParentRunner.java:268) at
org.robolectric.internal.SandboxTestRunner.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.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(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)
最新Robolectric4.3已经支持AndroidQ(https://github.com/robolectric/robolectric/releases)
如果有人想知道,我的解决方案是用
注释我的测试 类
@Config(sdk = Build.VERSION_CODES.O_MR1)
使用以下行在 app/src/test/resources
目录中创建一个 robolectric.properties
文件:
sdk=28
这将强制 Robolectric 使用 API 28 而不是 29。
对于Robolectric 4.3.1,我们可以使用以下备选方案:
- 运行 我们使用 Java 9 或更新版本进行测试。 (我们可以在运行测试配置中编辑JRE)
如果我们想 运行 我们的测试 Java 8,我们可以:
- 用 @Config 注释我们的测试 class 以模拟较低的 SDK(如 @bencri 和 @julio-mendoza 所述)。
像这样:
@RunWith(AndroidJUnit4::class)
@Config(sdk = Build.VERSION_CODES.P)
class LoginRobolectricTest {
//...
}
- 或者,如@farmerbb 所述,在
app/src/test/resources
文件夹中添加 robolectric.properties
文件,其中包含我们喜欢的 SDK 运行,例如:
sdk=28
Robolectric 何时与 Android SDK 29 兼容?我把 targetSdkVersion
和 compileSdkVersion
改成 29 是不是升级得太早了?
当我 运行 我的单元测试时,我得到这个巨大的堆栈跟踪:
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(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(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.access0(Injector.java:85)
at
org.robolectric.util.inject.Injector$ScopeBuilderProvider.create(Injector.java:551)
at
org.robolectric.util.inject.Injector$ScopeBuilderProvider.lambda$get[=12=](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.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.run(ParentRunner.java:290) at
org.junit.runners.ParentRunner.schedule(ParentRunner.java:71) at
org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) at
org.junit.runners.ParentRunner.access[=12=]0(ParentRunner.java:58) at
org.junit.runners.ParentRunner.evaluate(ParentRunner.java:268) at
org.robolectric.internal.SandboxTestRunner.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.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(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)
最新Robolectric4.3已经支持AndroidQ(https://github.com/robolectric/robolectric/releases)
如果有人想知道,我的解决方案是用
注释我的测试 类@Config(sdk = Build.VERSION_CODES.O_MR1)
使用以下行在 app/src/test/resources
目录中创建一个 robolectric.properties
文件:
sdk=28
这将强制 Robolectric 使用 API 28 而不是 29。
对于Robolectric 4.3.1,我们可以使用以下备选方案:
- 运行 我们使用 Java 9 或更新版本进行测试。 (我们可以在运行测试配置中编辑JRE)
如果我们想 运行 我们的测试 Java 8,我们可以:
- 用 @Config 注释我们的测试 class 以模拟较低的 SDK(如 @bencri 和 @julio-mendoza 所述)。
像这样:
@RunWith(AndroidJUnit4::class)
@Config(sdk = Build.VERSION_CODES.P)
class LoginRobolectricTest {
//...
}
- 或者,如@farmerbb 所述,在
app/src/test/resources
文件夹中添加robolectric.properties
文件,其中包含我们喜欢的 SDK 运行,例如:
sdk=28