Robolectric: run looper handler in my case

I have a very simple class that Handler has, when it processes a message, it sends a new message again:

 public class MyRepeatTask{ … public void startTask() { // send message with delay 5 sec handler.sendMessageDelayed(handler.obtainMessage(…), 5000); } Handler handler = new Handler() { @Override public void handleMessage(Message msg) { // I put a log for unit test System.out.println("handling message …"); // send message with delay again handler.sendMessageDelayed(handler.obtainMessage(…), 5000); } } } 

As you see above, when startTask() is called, the handler starts sending a message after 5 seconds. Then, in the handleMessage() callback, the Handler will again send a message with a delay of 5 seconds. The purpose of this is to repeatedly perform some task (for example, System.out.println() ).

I am testing the above Robolectric class:

 @RunWith(RobolectricTestRunner.class) public class MyRepeatTaskTest { @Test public void testStartTask() { MyRepeatTask task = new MyRepeatTask(); task.startTask(); // run looper of 'handler' in task ShadowLooper shadowLooper = Shadows.shadowOf(task.handler.getLooper()); shadowLooper.runToEndOfTasks(); // sleep for 30 seconds Thread.sleep(30 * 1000); } } 

I expect to see the System.out.println() handling message … " handling message … " every 5 seconds. However, when I run my test, I only see the message once in the terminal.

It seems that Handler s Looper only works for one task, and then it stopped.

If I'm right, how to keep the looper all the time in Robolectric? If I am wrong, why do I see only one log message?

=========== UPDATE ============

I tried @rds answer, I replaced Thread.sleep(30 * 1000); on:

 for (int i = 0; i < N; i++){ shadowLooper.runToEndOfTasks(); } 

Now I see N times " handling message … ". BUT, the entire test does not simulate a delay. I have a 5 second delay when sending a message using handler.sendMessageDelayed(handler.obtainMessage(…), 5000) , so the Robolectric framework does not mimic this delay message at all? How can I delay in my test?

+7
java android unit-testing robolectric
source share
3 answers

The problem is that when runToEndOfTasks(); called runToEndOfTasks(); at this stage, only one task is performed.

Instead of skipping the test thread, you should call shadowLooper.runToEndOfTasks(); N times to have N calls to your handler.

0
source share

I encountered similar problems when implementing a scheduled download from api-webservice. Instead, I used a timer instead of a handler. I used this to complete the task every day (or in your case after a few seconds). You can also set the number of times ...

Android Timer Help

0
source share

You seem to be looking for ShadowLooper#idle(long) . This will allow you to carefully advance the handler’s time and state whether the job is running at different intervals.

0
source share

All Articles