Robolectric:在我的案例中运行处理程序的looper

时间:2015-12-04 11:03:11

标签: java android unit-testing robolectric

我有一个非常简单的类,它有Handler,当它处理消息时它再次发送新消息:

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

如上所述,当调用startTask()时,处理程序将在5秒内开始发送消息。然后,在handleMessage()回调中,handler再次发送延迟5秒的消息。这样做的目的是重复执行某项任务(如System.out.println())。

我使用Robolectric测试上述课程:

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

我希望每5秒看一次System.out.println()消息“handling message …”。但是,当我运行测试时,我只在终端中看到一次的消息。

看起来handler的{​​{1}}只运行一个任务,然后就停止了。

如果我是对的,如何保持弯针在Robolectric一直运转?如果我错了,为什么我只看到一条日志消息?

==========更新===========

我尝试了@rds的答案,我将Looper替换为:

Thread.sleep(30 * 1000);

现在我可以看到N次“for (int i = 0; i < N; i++){ shadowLooper.runToEndOfTasks(); } ”。但是,整个测试并未模拟延迟。发送带有handling message …的消息时,我有5秒的延迟,是否因此Robolectric框架根本不模拟这种延迟消息?我怎么能在测试中延迟?

3 个答案:

答案 0 :(得分:0)

问题在于,当你致电runToEndOfTasks();时,现阶段只有一项任务。

不应让测试线程休眠,而是应该调用shadowLooper.runToEndOfTasks(); N次,以便对你的处理程序进行N次调用。

答案 1 :(得分:0)

在从api-webservice实施预定下载时,我遇到了类似的问题。除了处理程序之外,我还实现了一个计时器。我每天都用这个来完成一项任务(或者在几秒钟内完成)。您也可以设置次数......

Timer Reference Android

答案 2 :(得分:0)

看来你正在寻找ShadowLooper#idle(long)。这将允许您小心地提前处理程序的时间,并在不同的时间间隔内运行任务。