机器人支持测试中的死锁

时间:2019-03-16 20:12:12

标签: android firebase unit-testing admob robolectric

我有一个利用admob的应用程序,我使用robolectric进行活动单元测试。最近,当我尝试在某个单元测试课程中添加第二个活动启动时,我遇到了僵局。

我将尽力解决这个问题。我创建了一个最小的工作示例。

我面临的僵局是:

"Measurement Worker":
    at org.robolectric.util.Scheduler.remove(Scheduler.java:191)
    - waiting to lock <0x00000006c2ccf310> (a org.robolectric.util.Scheduler)
    at org.robolectric.shadows.ShadowMessage.unschedule(ShadowMessage.java:35)
    at org.robolectric.shadows.ShadowMessage.recycleUnchecked(ShadowMessage.java:50)
    at java.lang.invoke.LambdaForm$DMH/1366974691.invokeVirtual_L_V(LambdaForm$DMH)
    at java.lang.invoke.LambdaForm$BMH/534224098.reinvoke(LambdaForm$BMH)
    at java.lang.invoke.LambdaForm$MH/385364354.guardWithCatch(LambdaForm$MH)
    at java.lang.invoke.LambdaForm$MH/370640320.delegate(LambdaForm$MH)
    at java.lang.invoke.LambdaForm$MH/1706920634.guard(LambdaForm$MH)
    at java.lang.invoke.LambdaForm$MH/1997654846.linkToCallSite(LambdaForm$MH)
    at android.os.Message.recycleUnchecked(Message.java)
    at android.os.MessageQueue.$$robo$$android_os_MessageQueue$removeMessages(MessageQueue.java:698)
    - locked <0x00000006c2ccf2c8> (a android.os.MessageQueue)
    at java.lang.invoke.LambdaForm$DMH/194706439.invokeSpecial_L4_V(LambdaForm$DMH)
    at java.lang.invoke.LambdaForm$MH/1114217759.guardWithCatch(LambdaForm$MH)
    at java.lang.invoke.LambdaForm$reinvoker/856894939.dontInline(LambdaForm$reinvoker)
    at java.lang.invoke.LambdaForm$MH/585248983.guard(LambdaForm$MH)
    at java.lang.invoke.LambdaForm$MH/123955857.linkToCallSite(LambdaForm$MH)
    at android.os.MessageQueue.removeMessages(MessageQueue.java)
    at android.os.Handler.$$robo$$android_os_Handler$removeCallbacks(Handler.java:513)
    at java.lang.invoke.LambdaForm$DMH/984196143.invokeSpecial_LL_V(LambdaForm$DMH)
    at java.lang.invoke.LambdaForm$MH/1603578033.guardWithCatch(LambdaForm$MH)
    at java.lang.invoke.LambdaForm$reinvoker/324572218.dontInline(LambdaForm$reinvoker)
    at java.lang.invoke.LambdaForm$MH/910145967.guard(LambdaForm$MH)
    at java.lang.invoke.LambdaForm$MH/917035733.linkToCallSite(LambdaForm$MH)
    at android.os.Handler.removeCallbacks(Handler.java)
    at com.google.android.gms.measurement.internal.zzab.cancel(Unknown Source)
    at com.google.android.gms.measurement.internal.zzab.zzv(Unknown Source)
    at com.google.android.gms.measurement.internal.zzeg.zzd(Unknown Source)
    at com.google.android.gms.measurement.internal.zzeg.zza(Unknown Source)
    at com.google.android.gms.measurement.internal.zzee.run(Unknown Source)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at com.google.android.gms.measurement.internal.zzbx.run(Unknown Source)
"SDK 26 Main Thread":
    at org.robolectric.shadows.ShadowMessageQueue$1.run(ShadowMessageQueue.java:106)
    - waiting to lock <0x00000006c2ccf2c8> (a android.os.MessageQueue)
    at org.robolectric.util.Scheduler$ScheduledRunnable.run(Scheduler.java:386)
    at org.robolectric.util.Scheduler.runOneTask(Scheduler.java:278)
    - locked <0x00000006c2ccf310> (a org.robolectric.util.Scheduler)
    at org.robolectric.util.Scheduler.advanceTo(Scheduler.java:260)
    - locked <0x00000006c2ccf310> (a org.robolectric.util.Scheduler)
    at org.robolectric.util.Scheduler.advanceBy(Scheduler.java:243)
    - locked <0x00000006c2ccf310> (a org.robolectric.util.Scheduler)
    at org.robolectric.util.Scheduler.advanceBy(Scheduler.java:233)
    - locked <0x00000006c2ccf310> (a org.robolectric.util.Scheduler)
    at org.robolectric.util.Scheduler.setIdleState(Scheduler.java:88)
    - locked <0x00000006c2ccf310> (a org.robolectric.util.Scheduler)
    at org.robolectric.util.Scheduler.unPause(Scheduler.java:123)
    - locked <0x00000006c2ccf310> (a org.robolectric.util.Scheduler)
    at org.robolectric.shadows.ShadowLooper.unPause(ShadowLooper.java:347)
    at org.robolectric.shadows.ShadowLooper.runPaused(ShadowLooper.java:398)
    at org.robolectric.android.controller.ActivityController.visible(ActivityController.java:161)
    at org.robolectric.android.internal.LocalActivityInvoker.startActivity(LocalActivityInvoker.java:44)
    at androidx.test.core.app.ActivityScenario.launch(ActivityScenario.java:207)
    at androidx.test.core.app.ActivityScenario.launch(ActivityScenario.java:184)
    at name.example.DeadlockTest.launchActivity(DeadlockTest.java:14)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.robolectric.internal.SandboxTestRunner$2.lambda$evaluate$0(SandboxTestRunner.java:256)
    at org.robolectric.internal.SandboxTestRunner$2$$Lambda$29/942518407.run(Unknown Source)
    at org.robolectric.internal.bytecode.Sandbox.lambda$runOnMainThread$0(Sandbox.java:89)
    at org.robolectric.internal.bytecode.Sandbox$$Lambda$30/1943325854.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)

Found 1 deadlock.

单元测试代码:

@RunWith(RobolectricTestRunner.class)
public class DeadlockTest {
    @Test
    public void launchActivity() {
        for (int i=0; i<2; i++){
            try (ActivityScenario<DeadlockActivity> scenario = ActivityScenario.launch(DeadlockActivity.class)) {
            }
        }
    }
}

活动代码:

public class DeadlockActivity extends Activity {
    private AdView adView;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        adView = new AdView(this);
        adView.setAdSize(AdSize.BANNER);
        adView.setAdUnitId("ca-app-pub-3940256099942544/6300978111");
        AdRequest adRequest = new AdRequest.Builder().build();
        adView.loadAd(adRequest);
    }

    @Override
    public void onDestroy() {
        adView.destroy();
        super.onDestroy();
    }
}

app / build.gradle

apply plugin: 'com.android.application'

android {
    compileSdkVersion 28
    defaultConfig {
        applicationId "com.example"
        minSdkVersion 21
        versionCode 1
    }
    testOptions.unitTests.includeAndroidResources true
}

dependencies {
    implementation 'com.google.android.gms:play-services-ads:17.2.0'
    implementation 'com.google.firebase:firebase-core:16.0.8'

    testImplementation 'androidx.test.ext:junit:1.1.0'
    testImplementation 'org.robolectric:robolectric:4.2'
}

在我的环境中,死锁永远不会在循环的第一次迭代中发生,并且始终在第二次迭代中发生。

有什么想法吗?

1 个答案:

答案 0 :(得分:0)

将Firebase依赖关系更新为仅发行版解决了单元测试死锁问题。

dependencies {
    implementation 'com.google.android.gms:play-services-ads:17.2.0'
    releaseImplementation 'com.google.firebase:firebase-core:16.0.8'

    testImplementation 'androidx.test.ext:junit:1.1.0'
    testImplementation 'org.robolectric:robolectric:4.2'
}