Robolectric: java.lang.IllegalStateException: Iteration already started

Created on 14 Oct 2018  路  4Comments  路  Source: robolectric/robolectric

Description

I have the follow error when I use ShowCaseView:

java.lang.IllegalStateException: Iteration already started
    at android.view.ViewTreeObserver$CopyOnWriteArray.start(ViewTreeObserver.java:1157)
    at android.view.ViewTreeObserver.dispatchOnGlobalLayout(ViewTreeObserver.java:941)
    at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2250)
    at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1392)
    at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6752)
    at android.os.Handler.handleCallback(Handler.java:790)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at org.robolectric.shadows.ShadowMessageQueue.dispatchMessage(ShadowMessageQueue.java:141)
    at org.robolectric.shadows.ShadowMessageQueue.access$100(ShadowMessageQueue.java:32)
    at org.robolectric.shadows.ShadowMessageQueue$1.run(ShadowMessageQueue.java:120)
    at org.robolectric.util.Scheduler$ScheduledRunnable.run(Scheduler.java:362)
    at org.robolectric.util.Scheduler.runOneTask(Scheduler.java:261)
    at org.robolectric.util.Scheduler.advanceTo(Scheduler.java:242)
    at org.robolectric.util.Scheduler.advanceBy(Scheduler.java:225)
    at org.robolectric.util.Scheduler.advanceBy(Scheduler.java:215)
    at org.robolectric.util.Scheduler.setIdleState(Scheduler.java:82)
    at org.robolectric.util.Scheduler.unPause(Scheduler.java:117)
    at org.robolectric.shadows.ShadowLooper.unPause(ShadowLooper.java:310)
    at org.robolectric.shadows.ShadowLooper.runPaused(ShadowLooper.java:361)
    at org.robolectric.shadows.ShadowViewGroup.addView(ShadowViewGroup.java:30)
    at android.view.ViewGroup.addView(ViewGroup.java)
    at android.view.ViewGroup.addView(ViewGroup.java:4708)
    at android.view.ViewGroup.addView(ViewGroup.java:4681)
    at ru.dimorinny.showcasecard.ShowCaseView.show(ShowCaseView.java:377)
    at ru.dimorinny.showcasecard.ShowCaseView$1$1.onMeasured(ShowCaseView.java:293)
    at ru.dimorinny.showcasecard.util.MeasuredUtils$2.onMeasured(MeasuredUtils.java:40)
    at ru.dimorinny.showcasecard.util.MeasuredUtils.afterOrAlreadyMeasured(MeasuredUtils.java:49)
    at ru.dimorinny.showcasecard.util.MeasuredUtils.afterOrAlreadyMeasuredViews(MeasuredUtils.java:35)
    at ru.dimorinny.showcasecard.ShowCaseView$1.onMeasured(ShowCaseView.java:286)
    at ru.dimorinny.showcasecard.util.MeasuredUtils$3.onMeasured(MeasuredUtils.java:54)
    at ru.dimorinny.showcasecard.util.MeasuredUtils$1.onGlobalLayout(MeasuredUtils.java:21)
    at android.view.ViewTreeObserver.dispatchOnGlobalLayout(ViewTreeObserver.java:945)
    at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2250)
    at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1392)
    at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6752)
    at android.os.Handler.handleCallback(Handler.java:790)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at org.robolectric.shadows.ShadowMessageQueue.dispatchMessage(ShadowMessageQueue.java:141)
    at org.robolectric.shadows.ShadowMessageQueue.access$100(ShadowMessageQueue.java:32)
    at org.robolectric.shadows.ShadowMessageQueue$1.run(ShadowMessageQueue.java:120)
    at org.robolectric.util.Scheduler$ScheduledRunnable.run(Scheduler.java:362)
    at org.robolectric.util.Scheduler.runOneTask(Scheduler.java:261)
    at org.robolectric.util.Scheduler.advanceTo(Scheduler.java:242)
    at org.robolectric.util.Scheduler.advanceBy(Scheduler.java:225)
    at org.robolectric.util.Scheduler.advanceBy(Scheduler.java:215)
    at org.robolectric.util.Scheduler.runOrQueueRunnable(Scheduler.java:334)
    at org.robolectric.util.Scheduler.postDelayed(Scheduler.java:156)
    at org.robolectric.util.Scheduler.postDelayed(Scheduler.java:145)
    at org.robolectric.shadows.ShadowMessageQueue.enqueueMessage(ShadowMessageQueue.java:127)
    at android.os.MessageQueue.enqueueMessage(MessageQueue.java)
    at android.os.Handler.enqueueMessage(Handler.java:662)
    at android.os.Handler.sendMessageAtTime(Handler.java:631)
    at android.view.ViewRootImpl$ViewRootHandler.sendMessageAtTime(ViewRootImpl.java:3728)
    at android.os.Handler.sendMessageDelayed(Handler.java:601)
    at android.os.Handler.sendMessage(Handler.java:538)
    at android.view.ViewRootImpl.dispatchResized(ViewRootImpl.java:6451)
    at org.robolectric.util.ReflectionHelpers.callInstanceMethod(ReflectionHelpers.java:249)
    at org.robolectric.shadows.ShadowViewRootImpl.callDispatchResized(ShadowViewRootImpl.java:101)
    at org.robolectric.android.controller.ActivityController.visible(ActivityController.java:125)
    at com.valderas.leonardo.adefulproject.activity.NavigationBottomActivityTest.setUp(NavigationBottomActivityTest.kt:35)
    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.RunBefores.evaluate(RunBefores.java:24)
    at org.robolectric.internal.SandboxTestRunner$2.evaluate(SandboxTestRunner.java:253)
    at org.robolectric.internal.SandboxTestRunner.runChild(SandboxTestRunner.java:130)
    at org.robolectric.internal.SandboxTestRunner.runChild(SandboxTestRunner.java:42)
    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.robolectric.internal.SandboxTestRunner$1.evaluate(SandboxTestRunner.java:84)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
    at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
    at com.intellij.rt.execution.application.AppMainV2.main(AppMainV2.java:131)

Steps to Reproduce

Method in my activity:

   private fun validateShowCase(){
        if (viewModel.validateIfShowCaseViewShouldBeShown()) {
           ShowCaseView.Builder(this)
                    .withTypedPosition(
                            ViewPosition(fabMain)
                    )
                    .withContent(
                            getString(R.string.showcase_information_menu)
                    )
                    .build()
                    .show(this)
            viewModel.showCaseViewShowed()
        }

Test Class

@RunWith(RobolectricTestRunner::class)
@Config(constants = BuildConfig::class,
        sdk = [27],
        application = Application::class)
class NavigationBottomActivityTest : BaseTest() {

    private lateinit var controller: ActivityController<NavigationBottomActivity>
    private lateinit var activity: NavigationBottomActivity
    private lateinit var shadowActivity: ShadowActivity
    private lateinit var menuTournamentModel: MenuTournamentModel

    override fun setUp() {
        super.setUp()
        controller = Robolectric.buildActivity(NavigationBottomActivity::class.java).create().visible() // error here
        activity = controller.get()
        shadowActivity = Shadows.shadowOf(activity)
    }

Robolectric & Android Version

robolectricTest = '3.8'
compileSdkVersion = 27
minSdkVersion = 18
targetSdkVersion = 27

Link to a public git repo demonstrating the problem:

scheduler

Most helpful comment

We've done a complete rewrite of Robolectric's threading model, available to try now in 4.3-beta-1 that we hope will fix many issues with the legacy scheduler.

Please give it a try by annotating your test with @LooperMode(PAUSED).

Please reopen this issue if you continue to see problems.

All 4 comments

Likely related to the scheduler being IdleState.UNPAUSED...

Calling Robolectric.getForegroundThreadScheduler().pause(); solved this issue in my tests. I called that in my setup method.

We've done a complete rewrite of Robolectric's threading model, available to try now in 4.3-beta-1 that we hope will fix many issues with the legacy scheduler.

Please give it a try by annotating your test with @LooperMode(PAUSED).

Please reopen this issue if you continue to see problems.

Was this page helpful?
0 / 5 - 0 ratings