Search code examples
androidrobolectricgoogle-analytics-firebase

Google Analytics - NullPointerException in Test


I'm getting the following NPE in a Robolectric test on a Travis build-server, and I'm having trouble pinpointing why. I'm unable to reproduce this issue locally.

Anybody know what causes onServiceConnected to be called? That might help me pinpoint the issue. From what I can tell this is a Google Play Services - Google Analytics issue.

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)

To my knowledge, I'm not initializing GA anywhere for my unit tests. I have a general "fake" analytics tracker that gets used whenever tests are run. Just in case, I've added the following line in the constructor of my fake tracker which gets created in onCreate of the application:

GoogleAnalytics.getInstance(context).setAppOptOut(true);

In case this is of relevance, it's breaking on a box with Java 1.7.0_u55.

EDIT:

I saw the following in the logs of a failed test today. I'm not sure it was the cause of the crash though. Might give some insight.

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.

Looks like a problem with SQLite and GA?

Another Update:

For updates, see the linked github issue (https://github.com/robolectric/robolectric/issues/1075). I'm reverting back to v3 for the time being.


Solution

  • The solution of Akeem works for me.

    This is what I use for Robolectic 3.0, which has some changes:

    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");