Robolectric 测试在终端中失败,在 Android Studio 中成功

Robolectric tests fail in terminal, succeed in Android Studio

我最近开始从事一个新项目,其中包括基于 Robolectric 的单元测试。

当 运行 来自 Android Studio (v3.6) 时,所有测试都成功通过。
St运行gely,当我 运行 他们使用来自终端的 ./gradlew test 时,一些测试失败了,出现非常可怕的错误:

java.lang.VerifyError: Stack map does not match the one at exception handler 56
Exception Details:
  Location:
    com/google/android/gms/measurement/internal/zzjy.zza(Landroid/net/Uri;)Landroid/os/Bundle; @56: astore
  Reason:
    Type 'java/lang/String' (current frame, locals[5]) is not assignable to null (stack map, locals[5])
  Current Frame:
    bci: @51
    flags: { }
    locals: { 'com/google/android/gms/measurement/internal/zzjy', 'android/net/Uri', 'java/lang/String', 'java/lang/String', 'java/lang/String', 'java/lang/String' }
    stack: { 'java/lang/UnsupportedOperationException' }
  Stackmap Frame:
    bci: @56
    flags: { }
    locals: { 'com/google/android/gms/measurement/internal/zzjy', 'android/net/Uri', 'java/lang/String', 'java/lang/String', 'java/lang/String', null }
    stack: { 'java/lang/UnsupportedOperationException' }
  Bytecode:
    // redacted..    
  Exception Handler Table:
    bci [16, 53] => handler: 56
  Stackmap Table:
    same_frame(@6)
    full_frame(@53,{Object[#2],Object[#145],Object[#129],Object[#129],Object[#129],Object[#129]},{})
    full_frame(@56,{Object[#2],Object[#145],Object[#129],Object[#129],Object[#129],Null},{Object[#143]})
    full_frame(@74,{Object[#2],Object[#145],Object[#129],Object[#129],Object[#129],Object[#129]},{})
    same_frame(@104)
    append_frame(@128,Object[#172])
    same_frame(@143)
    same_frame(@160)
    same_frame(@177)
    append_frame(@201,Object[#129])
    append_frame(@225,Object[#129])
    append_frame(@249,Object[#129])
    append_frame(@273,Object[#129])
    append_frame(@297,Object[#129])
    full_frame(@300,{Object[#2],Object[#145],Object[#129],Object[#129],Object[#129],Object[#129]},{})
    at com.google.android.gms.measurement.internal.zzfl.<init>(com.google.android.gms:play-services-measurement-impl@@17.1.0:42)
    at com.google.android.gms.measurement.internal.zzfl.zza(com.google.android.gms:play-services-measurement-impl@@17.1.0:285)
    at com.google.firebase.analytics.FirebaseAnalytics.getInstance(com.google.android.gms:play-services-measurement-api@@17.1.0:9)
    // redacted..
    at org.robolectric.android.internal.AndroidTestEnvironment.lambda$installAndCreateApplication[=12=](AndroidTestEnvironment.java:276)
    at org.robolectric.android.internal.AndroidTestEnvironment$$Lambda/1286999442.run(Unknown Source)
    at org.robolectric.util.PerfStatsCollector.measure(PerfStatsCollector.java:75)
    at org.robolectric.android.internal.AndroidTestEnvironment.installAndCreateApplication(AndroidTestEnvironment.java:276)
    at org.robolectric.android.internal.AndroidTestEnvironment.setUpApplicationState(AndroidTestEnvironment.java:169)
    at org.robolectric.RobolectricTestRunner.beforeTest(RobolectricTestRunner.java:301)
    at org.robolectric.internal.SandboxTestRunner.lambda$evaluate[=12=](SandboxTestRunner.java:243)
    at org.robolectric.internal.SandboxTestRunner$$Lambda/968645498.run(Unknown Source)
    at org.robolectric.internal.bytecode.Sandbox.lambda$runOnMainThread[=12=](Sandbox.java:89)
    at org.robolectric.internal.bytecode.Sandbox$$Lambda/1700079137.call(Unknown Source)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)

为什么测试在 Android Studio 中通过,但在终端中失败?

Why the tests pass in Android Studio, but fail in terminal?

这是因为从 Android Studio 调用时使用的版本与从终端调用时使用的版本之间存在 JDK 版本不匹配。



Gradle 从终端调用时使用哪个 JDK 版本?

当来自终端的 运行 时,Gradle 使用 JAVA_HOME 中定义的版本 - 在我的机器上指向(旧版本)1.8.0-51.

当从 Android Studio 调用时,Gradle 使用哪个 JDK 版本?

Starting from version 2.2,最新的 OpenJDK 的副本与 Android Studio 捆绑在一起。
例如,Android Studio 3.6 使用 OpenJDK v1.8.0-212。

当 运行 您来自 Android Studio 的任务可以 found/set 在 Project Structure 时,您希望 Gradle 使用的 JDK 版本 > SDK Location > JDK Location。默认情况下,它配置为使用捆绑的 OpenJDK 版本。

我是怎么解决这个错误的?

为了重现 Android Studio 中的错误,我将 JDK Location 更改为 JAVA_HOME,运行 测试(来自 Android Studio) 又来了,瞧!我只在终端中看到的错误现在也出现在 Android Studio 中。

为了解决我在 运行 从终端进行测试时看到的失败,我已将 JAVA_HOME 指向的 JDK 更新为最新版本 (1.8.0-251) ,现在测试在 Android Studio 中和在 运行 使用 gradlew 来自终端时都通过了测试。