在使用JUnit时如何使TimerTask运行

10

我有一个像这样的函数:

private Timer timer = new Timer();

private void doSomething() {
    timer.schedule(new TimerTask() {
        public void run() {
            doSomethingElse();
        }
    },
    (1000));
}

我试图为我的代码编写JUnit测试,但是当特定地测试这段代码时,它们的行为不符合预期。通过使用EclEmma,我能够看到我的测试从未触发doSomethingElse()函数。

我该如何编写JUnit测试来等待足够长的时间以使TimerTask完成后再继续进行测试?


为什么你不直接调用 doSomethingElse() 呢? - CtrlF
3个回答

10

你可以这样做:

private Timer timer = new Timer();

private void doSomething() {
    final CountDownLatch latch = new CountDownLatch(1);

    timer.schedule(new TimerTask() {
        public void run() {
            doSomethingElse();
            latch.countDown();
        }
    },
    (1000));

    latch.await();
    // check results
}
CountDownLatch#await()方法会阻塞当前线程,直到在构造函数中指定的调用countDown()次数至少为一次。如果您想设置最大等待时间,可以向await()提供参数。
更多信息请参见:http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/CountDownLatch.html

5

JUnit并不适合运行多线程代码。当主线程退出时,它将停止所有其他线程。换句话说,如果您的线程调度程序在从@Test方法返回之前未上下文切换到运行新TimerTask的线程,则它将仅终止该线程并退出JVM,因此永远不会执行您的方法。

您可以像Stefan建议的那样放置一个Thread.sleep(long),或者使用不同的设计,可能是ScheduledThreadPoolExecutor,在其中您可以使用一些超时值awaitTermination


-2

在你的测试中,你可以使用Thread.sleep(1000)


3
最好的测试应该是快速的测试,并且不依赖于实时性。当你有很多测试时,如果使用实时模式,那些需要使用 sleep 的测试将会花费太长时间。 - Alex Yarmula

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接