Возникли проблемы при проведении инструментального тестирования с AndroidX LiveData и моделями просмотра моделей - PullRequest
0 голосов
/ 25 января 2019

После портирования проекта в библиотеку Android Jetpack ("AndroidX") у меня возникают проблемы с получением инструментальных тестов, включающих модель макета представления и манипулирование LiveData.

Я построил относительно простое приложение, показывающее ту же ошибку: https://github.com/Spheniscine/courtcounter/tree/4e9d413f56ccdbded54d72abeba448f281af1a7f

Само приложение работает нормально, но MainActivityTest завершится с ошибкой:

android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:8358)
at android.view.ViewRootImpl.invalidateChildInParent(ViewRootImpl.java:1364)
at android.view.ViewGroup.invalidateChild(ViewGroup.java:5433)
at android.view.View.invalidateInternal(View.java:13997)
at android.view.View.invalidate(View.java:13961)
at android.view.View.invalidate(View.java:13945)
at android.widget.TextView.checkForRelayout(TextView.java:8411)
at android.widget.TextView.setText(TextView.java:5011)
at android.widget.TextView.setText(TextView.java:4836)
at android.widget.TextView.setText(TextView.java:4811)
at com.github.spheniscine.udacityredone.courtcounter.ui.MainActivity$onCreate$$inlined$bindText$1.onChanged(LiveDataUtil.kt:45)
at androidx.lifecycle.LiveData.considerNotify(LiveData.java:113)
at androidx.lifecycle.LiveData.dispatchingValue(LiveData.java:131)
at androidx.lifecycle.LiveData.setValue(LiveData.java:289)
at androidx.lifecycle.MutableLiveData.setValue(MutableLiveData.java:33)
at com.github.spheniscine.udacityredone.courtcounter.util.LiveDataUtilKt.setTo(LiveDataUtil.kt:26)
at com.github.spheniscine.udacityredone.courtcounter.MainActivityTest.scoreTeamA_changes_whenViewModelSet(MainActivityTest.kt:46)
at java.lang.reflect.Method.invoke(Native Method)
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 androidx.test.internal.runner.junit4.statement.RunBefores.evaluate(RunBefores.java:80)
at org.junit.rules.TestWatcher$1.evaluate(TestWatcher.java:55)
at androidx.test.rule.ActivityTestRule$ActivityStatement.evaluate(ActivityTestRule.java:531)
at org.junit.rules.RunRules.evaluate(RunRules.java:20)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at androidx.test.ext.junit.runners.AndroidJUnit4.run(AndroidJUnit4.java:104)
at org.junit.runners.Suite.runChild(Suite.java:128)
at org.junit.runners.Suite.runChild(Suite.java:27)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at org.junit.runner.JUnitCore.run(JUnitCore.java:115)
at androidx.test.internal.runner.TestExecutor.execute(TestExecutor.java:56)
at androidx.test.runner.AndroidJUnitRunner.onStart(AndroidJUnitRunner.java:388)
at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:1960)

Ответы [ 2 ]

0 голосов
/ 12 июня 2019

Если у вас проблемы с variable.value = true, это потому, что вы не работаете с основным потоком.Для этого у LiveData есть специальный метод.Попробуйте использовать:

variable.postValue(true)

На основании документации:

setValue():

Устанавливает значение.Если есть активные наблюдатели, значение будет отправлено им.Этот метод должен вызываться из основного потока.

postValue():

Отправляет задачу в основной поток для установки заданного значения.Если вы вызывали этот метод несколько раз до того, как основной поток выполнил опубликованную задачу, будет отправлено только последнее значение.

0 голосов
/ 19 марта 2019

Единственное, что сработало для меня, это использование runOnUiThread для выполнения строки кода, которая касается иерархии представления:

  @Test
  fun loadingIndicatorShownWhenLiveDataUpdated() {
    activityRule.activity.runOnUiThread {
      loadingLiveData.value = true
    }

    onView(withId(R.id.progressBar))
      .check(matches(withEffectiveVisibility(Visibility.VISIBLE)))
  }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...