带有Play服务的Robolectric 3中的异步测试代码

时间:2015-05-22 08:12:32

标签: android junit robolectric

我正在使用 Robolectric 3 rc2 与OkHttp Mock WebServer和Google Play服务。

我需要测试json的解析以及使用模拟服务器和服务器客户端已经使用的相关处理。整个服务器客户端调用在后台中运行,并带有 okhttp异步调用。整个项目如果是图书馆项目。

完整代码 here

Gradle配置:

testCompile 'org.apache.maven:maven-ant-tasks:2.1.3'
testCompile ("org.robolectric:robolectric:3.0-rc2"){
    exclude module: 'commons-logging'
    exclude module: 'httpclient'
}
testCompile 'com.google.android.gms:play-services:7.0.0'
testCompile ("org.robolectric:shadows-play-services:3.0-rc2"){
    exclude module: 'commons-logging'
    exclude module: 'httpclient'
}
testCompile 'org.robolectric:shadows-support-v4:3.0-rc2'
testCompile 'org.assertj:assertj-core:1.7.0'
testCompile 'com.squareup.okhttp:mockwebserver:1.2.1'

我正在运行测试为什么命令行:

  

./ gradlew mymodule:clean mymodule:assembleDebug mymodule:testDebug --info

错误

我收到与Google Play服务相关的错误 java.lang.IllegalStateException: Calling this from your main thread can lead to deadlock

当gettign AdvertisingId ......我肯定做错了什么......

完成堆栈跟踪:

java.lang.RuntimeException: java.lang.IllegalStateException: Calling this from your main thread can lead to deadlock
    at org.robolectric.util.SimpleFuture.run(SimpleFuture.java:57)
    at org.robolectric.shadows.ShadowAsyncTask$2.run(ShadowAsyncTask.java:93)
    at org.robolectric.util.Scheduler.runOrQueueRunnable(Scheduler.java:218)
    at org.robolectric.util.Scheduler.postDelayed(Scheduler.java:73)
    at org.robolectric.util.Scheduler.post(Scheduler.java:60)
    at org.robolectric.shadows.ShadowAsyncTask.execute(ShadowAsyncTask.java:90)
    at android.os.AsyncTask.execute(AsyncTask.java)
    at com.example.sdk.adServer.ServerClient.<init>(ServerClient.java:101)
    at com.example.sdk.ServerClientTest.testLongTask(ServerClientTest.java:123)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
    at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:31)
    at org.robolectric.RobolectricTestRunner$2.evaluate(RobolectricTestRunner.java:235)
    at org.junit.runners.BlockJUnit4ClassRunner.runNotIgnored(BlockJUnit4ClassRunner.java:79)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:71)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:49)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
    at org.robolectric.RobolectricTestRunner$1.evaluate(RobolectricTestRunner.java:168)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
    at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecuter.runTestClass(JUnitTestClassExecuter.java:86)
    at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecuter.execute(JUnitTestClassExecuter.java:49)
    at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassProcessor.processTestClass(JUnitTestClassProcessor.java:64)
    at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.processTestClass(SuiteTestClassProcessor.java:50)
    at org.gradle.messaging.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35)
    at org.gradle.messaging.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
    at org.gradle.messaging.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:32)
    at org.gradle.messaging.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:93)
    at com.sun.proxy.$Proxy2.processTestClass(Unknown Source)
    at org.gradle.api.internal.tasks.testing.worker.TestWorker.processTestClass(TestWorker.java:106)
    at org.gradle.messaging.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35)
    at org.gradle.messaging.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
    at org.gradle.messaging.remote.internal.hub.MessageHub$Handler.run(MessageHub.java:360)
    at org.gradle.internal.concurrent.DefaultExecutorFactory$StoppableExecutorImpl$1.run(DefaultExecutorFactory.java:64)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.IllegalStateException: Calling this from your main thread can lead to deadlock
    at com.google.android.gms.common.internal.zzx.zzbe(Unknown Source)
    at com.google.android.gms.common.internal.zzx.zzbe(Unknown Source)
    at com.google.android.gms.ads.identifier.AdvertisingIdClient.finish(Unknown Source)
    at com.google.android.gms.ads.identifier.AdvertisingIdClient.finish(Unknown Source)
    at com.google.android.gms.ads.identifier.AdvertisingIdClient.getAdvertisingIdInfo(Unknown Source)
    at com.google.android.gms.ads.identifier.AdvertisingIdClient.getAdvertisingIdInfo(Unknown Source)
    at com.example.sdk.adServer.ServerClient$RetrieveAdvertisingId.doInBackground(ServerClient.java:459)
    at com.example.sdk.adServer.ServerClient$RetrieveAdvertisingId.doInBackground(ServerClient.java:452)
    at org.robolectric.util.ReflectionHelpers$3.run(ReflectionHelpers.java:144)
    at org.robolectric.util.ReflectionHelpers.traverseClassHierarchy(ReflectionHelpers.java:241)
    at org.robolectric.util.ReflectionHelpers.callInstanceMethod(ReflectionHelpers.java:138)
    at org.robolectric.shadows.ShadowAsyncTaskBridge.doInBackground(ShadowAsyncTaskBridge.java:20)
    at org.robolectric.shadows.ShadowAsyncTask$BackgroundWorker.call(ShadowAsyncTask.java:147)
    at org.robolectric.util.SimpleFuture.run(SimpleFuture.java:52)

1 个答案:

答案 0 :(得分:-1)

java.lang.RuntimeException: java.lang.IllegalStateException: Calling this from your main thread can lead to deadlock

来自异常的消息明确描述了您所做的错误。显然你不应该在UI线程上调用AdvertisingIdClient,因为库不允许它(原因如上所述。它可能导致死锁)。

因此,您必须使用 AsyncTask 或任何其他后台任务库才能调用此API。

AsyncTask<Void, Void, String> task = new AsyncTask<Void, Void, String>() {
        @Override
        protected String doInBackground(Void... params) {
            AdvertisingIdClient.Info idInfo;
            String advertId = null;
            try {
                idInfo = AdvertisingIdClient.getAdvertisingIdInfo(context);
                advertId = idInfo.getId();
            } catch (GooglePlayServicesNotAvailableException|GooglePlayServicesRepairableException|IOException e) {
                e.printStackTrace();
            }
            return advertId;
        }

        @Override
        protected void onPostExecute(final String advertId) {
            KakaoTaskQueue.getInstance().addTask(new KakaoResultTask<EventsLogResponse>(callback) {
                @Override
                public EventsLogResponse call() throws Exception {
                    if (advertId == null)
                        throw new IllegalAccessException("Could not get adid from the device.");
                    rootEvent.setFrom(advertId);
                    return EventsApi.requestLoggingEvents(rootEvent, leafEvents);
                }
            });
        }
    };
    task.execute();

这是您使用 AsyncTask AdvertisingIdClient 类中调用 getAdvertisingIdInfo 方法的方法。如果您有任何其他问题,请评论:)