当我测试执行创建子线程的方法时,JUnit测试在子线程之前结束并将其终止。
如何强制JUnit等待子线程完成执行?
由于
答案 0 :(得分:8)
在阅读了问题和一些评论后,您需要的是单元测试异步操作的技术。 doSomething()立即返回,但您希望测试代码等待其完成,然后进行一些验证。
问题是测试不知道调用产生的线程,所以显然它没有办法等待它们。人们可以想到许多复杂的(也可能是有缺陷的)方法来解决这个问题,但在我看来,这里存在一个设计问题。单元测试应该模拟某个API的客户端,它不应该假设任何有关实现的内容;它应该只测试功能,如API及其文档所反映的那样。因此,我会避免尝试检测和跟踪异步调用创建的线程。相反,如果需要,我会改进测试类的API。异步调用所属的类应该提供一些检测终止的机制。我可以想到3种方法,但可能还有更多:
1)允许注册一旦操作完成后收到通知的监听器
2)提供操作的同步版本。该实现可以调用异步版本,然后阻塞直到完成。如果类不应该暴露这样的方法,它的可见性可以减少到包保护,以便测试可以访问它。
3)在某些可见对象上使用wait-notify模式。
如果类没有提供这样的机制,那么它不是真正可测试的,更糟糕的是,它可能也不是非常可重用的。
答案 1 :(得分:2)
尝试在创建的线程上使用thread.join()。这将等待该线程死亡。
修改:要避免这种情况,请在测试中尝试Thread.getThreadGroup().setDaemon(true);
,或者在setUp()
方法中尝试。我没有测试过这个。
守护程序线程组在其最后一个线程停止或其最后一个线程组被销毁时自动销毁。
我想知道JUnit是否在测试结束后立即调用System.exit()
或其他东西。
答案 2 :(得分:1)
@Eyal概述的基本技术是ConcurrentUnit的用途。一般用法是:
有关详细信息,请参阅ConcurrentUnit页面。
答案 3 :(得分:0)
或许可以使用 ExecutorService 对线程进行分组,然后使用关闭和awaitTermination方法?
条件是使用Runnable或Future,而不是Threads本身。
答案 4 :(得分:0)
while (s.isRunning()) {
try {
Thread.sleep(SLEEP_TIME);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
您可以尝试阻止JUnit线程并让它等待您的线程完成。需要Thread.sleep()
以便您的线程不会占用CPU。在这个例子中,s将是你需要拥有isRunning()
方法的线程,这样你就可以检查线程是否仍然每SLEEP_TIME
毫秒运行一次。我知道这不是最好的解决方案,但是如果你只有2个线程并且你不希望JUnit杀死你的线程,这是有效的。 while循环导致此JUnit线程保持活动状态并等待其他线程完成。
答案 5 :(得分:0)
在Java中,尝试使用CountDownLatch使主线程等待直到子线程完成。
@Test
public void myTest() {
CountDownLatch countDownLatch = new CountDownLatch(1);
new Thread(new Runnable() {
@Override
public void run() {
//write your logic here
countDownLatch.countDown();
}
}).start();
//wait until the child thread completed.
countDownLatch.await();
}