Robolectric and the UI thread

4,514 views
Skip to first unread message

Nate Bourgoin

unread,
Oct 9, 2013, 12:04:57 PM10/9/13
to robol...@googlegroups.com
Greetings,

I'm trying to test that some behavior happens as a result of the following using Robolectric:

        mDisplayTimer = new Timer();
        mDisplayTimer.schedule(new TimerTask() {
            @Override
            public void run() {
                getActivity().runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        timerDone();
                    }
                });
            }
        }, mMinSplashSleepTime);

Where timerDone() does something along the lines of:

private void timerDone() {
   // starts a new activity
   new Intent(getActivity(),nextActivity.class));

   // calls finish on the existing activity
   getActivity().finish();
}

And the test does something along the lines of:

@Test
public void testNextActivity() {
  // Do the test scenario above

  // Assert the next activity was called
  assert(nextAcitvity.startActivityCalled);
}

Note that startActivityCalled is a static property in a mocked activity created for testing.

And the test does some verification to show that nextActivity was called

Where timerDone() sets some static state and the test validates that this static state is set. If I remove the runOnUIThread bit so that timerDone() doesn't run on the UI thread and remove the finish() so that it can run, the test works fine and the expected state is set. When it is run on the UI thread, the state is never set.

I have dug through the docs but am obviously missing something.

I have tried a mix of the following in the test before asserting to get the UI task to run:

        Robolectric.getUiThreadScheduler().advanceBy(...);
        Robolectric.getUiThreadScheduler().runTasks(10);
        Robolectric. getBackgroundScheduler().advanceBy(...);
        Robolectric.getUiThreadScheduler().runTasks(10);
        Robolectric.runUiThreadTasksIncludingDelayedTasks();
        Robolectric.runBackgroundTasks();
        Thread.sleep(SLEEP_TIME_MS);

Any help would be appreciated.

Nate Bourgoin

unread,
Oct 9, 2013, 12:10:13 PM10/9/13
to robol...@googlegroups.com
Note that I was using Robolectric 2.1.1 and just tested with 2.2

Nate Bourgoin

unread,
Oct 9, 2013, 1:20:27 PM10/9/13
to robol...@googlegroups.com
As it always is, figure it out as soon as its asked to a wider audience.

If I do a small sleep before runUIThreadTasksIncludingDelayedTasks() in the test it works fine. Not sure why we are returning before the task is on the UIthread queue (or if this is expected behavior) but I'm unblocked at least.

Clarification would still be great.


On Wednesday, October 9, 2013 12:04:57 PM UTC-4, Nate Bourgoin wrote:

Darien Alvarez

unread,
Jan 28, 2014, 3:48:50 PM1/28/14
to robol...@googlegroups.com

can you help me i have the same issue can you post all your code to follow your hack???

Nate Bourgoin

unread,
Jan 28, 2014, 3:55:53 PM1/28/14
to robol...@googlegroups.com
The hack was :

public void testFoo() {

    // Do test setup work

    // Fast forward to the end of the UI queue
    Thread.sleep(50); // Work around a race condition where the UI thread doesn't yet have the task in its queue
    Robolectric.runUiThreadTasksIncludingDelayedTasks();

    // Perform whatever validation I needed
}


On Tue, Jan 28, 2014 at 3:48 PM, Darien Alvarez <dalv...@devsu.com> wrote:

can you help me i have the same issue can you post all your code to follow your hack???

--
You received this message because you are subscribed to a topic in the Google Groups "Robolectric" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/robolectric/mlXNko2NFE0/unsubscribe.
To unsubscribe from this group and all its topics, send an email to robolectric...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.



--
Sincerely,

Nathan Bourgoin
NateBo...@gmail.com

Darien Alvarez

unread,
Jan 29, 2014, 9:27:15 AM1/29/14
to robol...@googlegroups.com
Thank you very much, yesterday late i found the same approach:

CountDownLatch latch = new CountDownLatch(1);

latch.await(2, TimeUnit.SECONDS);

Robolectric.runUiThreadTasksIncludingDelayedTasks();


Actually i will study how i can change my asyncTask by RoboAsyncTask maybe i must refactor my code but many people says that roboasynctask are better and faster.

Thank you very much for your help, i appreciate that,


Darien

Mike Grafton

unread,
Jan 30, 2014, 4:27:59 PM1/30/14
to robol...@googlegroups.com
Hey guys,

+1 to trying AsyncTask or RoboAsync Task. 

I would stay away from any calls to Thread.sleep() in a test. That is recipe for flaky test disaster, and/or tests that are unnecessarily slow.

Going further, I like to avoid running any other Threads besides the main test thread.  I am not very familiar with Timer, but it appears that you need to wait because it is actually running its task on a separate thread.

Robolectric goes through great pains to make it possible to test asynchronous behavior without having fire up actual threads. It takes control of the two main Android event "loopers" (UI and background) and allows you to run tasks under the complete control of the test itself. This allows very fine-grained control of sequences of events that is impossible if the looper threads were running continuously. By default, AsyncTask is hooked into this mechanism; unfortunately Timer doesn't seem to be.

Mike


You received this message because you are subscribed to the Google Groups "Robolectric" group.
To unsubscribe from this group and stop receiving emails from it, send an email to robolectric...@googlegroups.com.

Nate Bourgoin

unread,
Jan 30, 2014, 10:34:03 PM1/30/14
to robol...@googlegroups.com
Did you try the sleep, just to see if it gets you some results (and to verify that it works as we expect)

Volodia Chornenkyy

unread,
Aug 19, 2016, 7:49:09 AM8/19/16
to Robolectric
Thanks, this approach also work for me. The only change I made is use the ShadowLooper instead of Robolectric now.
Reply all
Reply to author
Forward
0 new messages