Android 谷歌分析-测试中的NullPointerException

Android 谷歌分析-测试中的NullPointerException,android,robolectric,google-analytics-firebase,Android,Robolectric,Google Analytics Firebase,我在Travis build服务器上进行的机器人分子测试中得到了以下NPE,我很难找出原因。我无法在本地复制此问题 有人知道调用onServiceConnected的原因吗?这可能有助于我查明问题所在。据我所知,这是一个谷歌播放服务-谷歌分析问题 java.lang.NullPointerException at com.google.android.gms.analytics.c$a.onServiceConnected(Unknown Source) at com.googl

我在Travis build服务器上进行的机器人分子测试中得到了以下NPE,我很难找出原因。我无法在本地复制此问题

有人知道调用onServiceConnected的原因吗?这可能有助于我查明问题所在。据我所知,这是一个谷歌播放服务-谷歌分析问题

java.lang.NullPointerException
    at com.google.android.gms.analytics.c$a.onServiceConnected(Unknown Source)
    at com.google.android.gms.analytics.c$a.onServiceConnected(Unknown Source)
    at org.robolectric.shadows.ShadowApplication$2.run(ShadowApplication.java:257)
    at org.robolectric.util.Scheduler$PostedRunnable.run(Scheduler.java:162)
    at org.robolectric.util.Scheduler.runOneTask(Scheduler.java:107)
    at org.robolectric.util.Scheduler.advanceTo(Scheduler.java:92)
    at org.robolectric.util.Scheduler.advanceToLastPostedRunnable(Scheduler.java:68)
    at org.robolectric.util.Scheduler.unPause(Scheduler.java:25)
    at org.robolectric.shadows.ShadowLooper.unPause(ShadowLooper.java:228)
    at org.robolectric.shadows.ShadowLooper.runPaused(ShadowLooper.java:267)
    at org.robolectric.util.ActivityController.create(ActivityController.java:144)
    at org.robolectric.util.ActivityController.create(ActivityController.java:154)
    at com.company.search.activities.loginjoin.LoginActivityTest.setup(LoginActivityTest.java:20)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:24)
    at org.robolectric.RobolectricTestRunner$2.evaluate(RobolectricTestRunner.java:250)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
    at org.robolectric.RobolectricTestRunner$1.evaluate(RobolectricTestRunner.java:177)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
    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:69)
    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:105)
    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:355)
    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)
据我所知,我不会在任何地方为我的单元测试初始化GA。我有一个通用的“假”分析跟踪器,可以在测试运行时使用。为了以防万一,我在我的假跟踪器的构造函数中添加了以下行,该跟踪器是在应用程序的onCreate中创建的:

GoogleAnalytics.getInstance(context).setAppOptOut(true);
如果这与Java 1.7.0_55相关,那么它就是在一个盒子上打破的

编辑: 我在今天失败测试的日志中看到了以下内容。但我不确定这是坠机的原因。也许能给我们一些启示

E/GAV3: Thread[GAThread,5,main]: Error on GAThread: java.lang.NullPointerException
    at org.robolectric.shadows.ShadowLooper.getMainLooper(ShadowLooper.java:66)
    at android.os.Looper.getMainLooper(Looper.java)
    at android.database.sqlite.SQLiteDatabase.isMainThread(SQLiteDatabase.java:391)
    at android.database.sqlite.SQLiteDatabase.getThreadDefaultConnectionFlags(SQLiteDatabase.java:381)
    at android.database.sqlite.SQLiteProgram.__constructor__(SQLiteProgram.java:58)
    at android.database.sqlite.SQLiteProgram.<init>(SQLiteProgram.java:41)
    at android.database.sqlite.SQLiteStatement.<init>(SQLiteStatement.java:31)
    at android.database.sqlite.SQLiteDatabase.compileStatement(SQLiteDatabase.java:992)
    at android.database.DatabaseUtils.longForQuery(DatabaseUtils.java:799)
    at android.database.sqlite.SQLiteDatabase.getVersion(SQLiteDatabase.java:862)
    at android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:242)
    at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:164)
    at com.google.android.gms.analytics.ac$a.getWritableDatabase(Unknown Source)
    at com.google.android.gms.analytics.ac$a.getWritableDatabase(Unknown Source)
    at com.google.android.gms.analytics.ac.G(Unknown Source)
    at com.google.android.gms.analytics.ac.G(Unknown Source)
    at com.google.android.gms.analytics.ac.i(Unknown Source)
    at com.google.android.gms.analytics.ac.i(Unknown Source)
    at com.google.android.gms.analytics.s.bk(Unknown Source)
    at com.google.android.gms.analytics.s.bk(Unknown Source)
    at com.google.android.gms.analytics.s.bJ(Unknown Source)
    at com.google.android.gms.analytics.s.bJ(Unknown Source)
    at com.google.android.gms.analytics.s.a(Unknown Source)
    at com.google.android.gms.analytics.s$2.run(Unknown Source)
    at com.google.android.gms.analytics.s$2.run(Unknown Source)
    at com.google.android.gms.analytics.t.run(Unknown Source)
    at com.google.android.gms.analytics.t.run(Unknown Source)

E/GAV3: Thread[GAThread,5,main]: Google Analytics is shutting down.
E/GAV3:Thread[GAThread,5,main]:GAThread上的错误:java.lang.NullPointerException
位于org.roblectric.shadows.ShadowLooper.getMainLooper(ShadowLooper.java:66)
位于android.os.Looper.getMainLooper(Looper.java)
位于android.database.sqlite.SQLiteDatabase.isMainThread(SQLiteDatabase.java:391)
位于android.database.sqlite.SQLiteDatabase.getThreadDefaultConnectionFlags(SQLiteDatabase.java:381)
在android.database.sqlite.SQLiteProgram.\uuuuu构造函数\uuuuu(SQLiteProgram.java:58)
位于android.database.sqlite.SQLiteProgram.(SQLiteProgram.java:41)
位于android.database.sqlite.SQLiteStatement.(SQLiteStatement.java:31)
位于android.database.sqlite.SQLiteDatabase.compileStatement(SQLiteDatabase.java:992)
位于android.database.DatabaseUtils.longForQuery(DatabaseUtils.java:799)
位于android.database.sqlite.SQLiteDatabase.getVersion(SQLiteDatabase.java:862)
位于android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:242)
位于android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:164)
位于com.google.android.gms.analytics.ac$a.getWritableDatabase(未知来源)
位于com.google.android.gms.analytics.ac$a.getWritableDatabase(未知来源)
位于com.google.android.gms.analytics.ac.G(未知来源)
位于com.google.android.gms.analytics.ac.G(未知来源)
位于com.google.android.gms.analytics.ac.i(未知来源)
位于com.google.android.gms.analytics.ac.i(未知来源)
在com.google.android.gms.analytics.s.bk(未知来源)
在com.google.android.gms.analytics.s.bk(未知来源)
在com.google.android.gms.analytics.s.bJ(未知来源)
在com.google.android.gms.analytics.s.bJ(未知来源)
位于com.google.android.gms.analytics.s.a(未知来源)
在com.google.android.gms.analytics.s$2.run(未知来源)
在com.google.android.gms.analytics.s$2.run(未知来源)
位于com.google.android.gms.analytics.t.run(未知来源)
位于com.google.android.gms.analytics.t.run(未知来源)
E/GAV3:Thread[GAThread,5,main]:谷歌分析正在关闭。
看起来SQLite和GA有问题吗

另一个更新:


有关更新,请参阅链接的github问题()。我现在回到v3

这就是我发现的(并在我的案例中解决了): 在某个地方(可能在初始化Google Analytics时),有一个启动服务的调用

我以为这个电话是为了启动我的一个应用程序服务,所以我加了一句

Robolectric.getShadowApplication().setComponentNameAndServiceForBindService(
            new ComponentName(Robolectric.application, MyService.class),
            new StalkerService() {
                @Override
                public Context getApplicationContext() {
                    return Robolectric.application;
                }
            }.onBind(null)
    );
在我的测试应用程序代码中,在调用
super.onCreate
之前。 很高兴,它解决了我的问题-没有更多的NPE,所有的测试都通过了

但是,后来我注意到这是一个非常奇怪的解决方案,因为我为我的服务提供了Robolectric绑定器,而不是GA服务。。。但它起作用了,我不知道为什么。
因此,我将把它留在这里,让您测试它是否也解决了您的问题。

解决方法是在所有测试套件中添加以下行(因为您不知道将首先运行哪个测试用例)

或者,您可以为不绑定服务的应用程序创建自定义卷影类:

import android.app.Application;
import android.content.Intent;
import android.content.ServiceConnection;
import android.util.Log;

import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
import org.robolectric.shadows.ShadowApplication;


@Implements(Application.class)
public class MyShadowApplication extends ShadowApplication {
    @Implementation
    public boolean bindService(Intent intent, final ServiceConnection serviceConnection, int i) {
        Log.d("Robolectric", intent.getAction());
        return false;
    }
}
并使用shadow类运行所有测试用例

@Config(emulateSdk = 18, shadows = {MyShadowApplication.class})

Akeem的解决方案对我有效

这是我在Robolectic 3.0中使用的,它有一些变化:

import org.robolectric.RuntimeEnvironment;
import org.robolectric.Shadows;
import org.robolectric.shadows.ShadowApplication;

ShadowApplication shadowApplication = Shadows.shadowOf(RuntimeEnvironment.application);
shadowApplication.declareActionUnbindable("com.google.android.gms.analytics.service.START");

我不完全确定这里的答案,但我认为你们看到这一点是因为机器人电气的工作方式。在某些情况下,如反射,机器人电气是否可能无法正常工作?还有一个类似的问题。也许这会有帮助?。
import org.robolectric.RuntimeEnvironment;
import org.robolectric.Shadows;
import org.robolectric.shadows.ShadowApplication;

ShadowApplication shadowApplication = Shadows.shadowOf(RuntimeEnvironment.application);
shadowApplication.declareActionUnbindable("com.google.android.gms.analytics.service.START");