Intereting Posts
Предотвращение сканирования медиа-сканера с помощью JPG, загруженного с помощью DownloadManager на Android? (Разработчик) Ищете универсальный стиль TabHost, который будет работать на Android, HTC Sense, Samsung и т. Д. Добавьте маркеры 1000 в android Googlemap Кнопка меню Android не отображается Значение, генерируемое с помощью случайной функции () Линейная компоновка в scrollview не занимает полную высоту Как получить и установить (изменить) ID3-тег (метаданные) аудиофайлов? Как я могу предотвратить дикую прокрутку, когда поле формы ввода фиксированной позиции получает фокус? Одиночное приложение для Android Android SnackBar: ошибка раздувания SnackbarLayout Android TextView Hyperlink Android: весь ListView изменяет цвет в фокусе, а не только дочерний элемент ListView Как играть в InputStream аудиофайла, который не входит в URL-адрес или хранилище? Создание TextView из XML-файла шаблона Получить ширину родительского макета

Google Analytics – исключение NullPointerException в тесте

Я получаю следующий NPE в тесте Robolectric на сервере сборки Travis, и у меня возникают проблемы с определением причины. Я не могу воспроизвести эту проблему локально.

Кто-нибудь знает, какие причины onServiceConnected будут вызваны? Это может помочь мне определить проблему. Из того, что я могу сказать, это проблема Google Play Services – Google Analytics.

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_u55.

РЕДАКТИРОВАТЬ:

Сегодня я видел следующее в журналах неудавшегося теста. Я не уверен, что это было причиной аварии. Можете дать некоторое представление.

 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.sa(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. 

Похож на проблему с SQLite и GA?

Еще одно обновление:

Для получения обновлений см. Связанную проблему github ( https://github.com/robolectric/robolectric/issues/1075 ). На данный момент я возвращаюсь к v3.

Решение 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"); 

Исправление состоит в том, чтобы добавить следующие строки во ВСЕХ ваших наборов тестов (потому что вы не знаете, какой тестовый пример будет запущен первым)

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

Кроме того, вы можете создать собственный теневой класс для своего приложения, которое не связывает службы:

 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; } } 

И запустите все ваши тестовые примеры с помощью теневого класса

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

Это то, что я выяснил (и решил в моем случае): Где-то (возможно, при инициализации Google Analytics) есть вызов для запуска службы.

Я думал, что этот звонок должен был запустить одно из моих приложений, поэтому я добавил

 Robolectric.getShadowApplication().setComponentNameAndServiceForBindService( new ComponentName(Robolectric.application, MyService.class), new StalkerService() { @Override public Context getApplicationContext() { return Robolectric.application; } }.onBind(null) ); 

В моем коде TestApplication, перед вызовом super.onCreate . К счастью, это решило мою проблему – не больше NPE, и все тесты проходят.

Но потом я заметил, что это очень странное решение, так как я предоставляю Robolectric связующим для моей службы, а не службы GA … Но это работает, и я не знаю, почему. Итак, я собираюсь оставить его здесь, чтобы вы могли проверить, исправляет ли он ваши проблемы.