我有一个JUnit测试,我想同步等待一段时间。我的JUnit测试看起来像这样:
@Test
public void testExipres(){
SomeCacheObject sco = new SomeCacheObject();
sco.putWithExipration("foo", 1000);
// WAIT FOR 2 SECONDS
assertNull(sco.getIfNotExipred("foo"));
}
我尝试了Thread.currentThread().wait()
,但它抛出了非法监视器状态异常(如预期)。
有什么窍门吗?还是我需要一个不同的显示器?
9条答案
按热度按时间j7dteeu81#
Thread.sleep(2000);
怎么样?:)mftmpeh82#
Thread.sleep()可以在大多数情况下工作,但通常如果你在等待,你实际上是在等待一个特定的条件或状态发生。Thread.sleep()不能保证你所等待的任何事情实际上已经发生了。
例如,如果您正在等待一个休息请求,它通常会在5秒内返回,但如果您将睡眠时间设置为5秒,而当天您的请求会在10秒内返回,则测试将失败。
为了解决这个问题,JayWay有一个很棒的实用程序,叫做Awatility,它非常适合确保在你继续前进之前出现特定的情况。
它有一个很好的流畅的api以及
https://github.com/jayway/awaitility
q7solyqu3#
如果你的静态代码分析器(如SonarQube)投诉,但你不能想到另一种方式,而不是睡觉,你可以尝试与黑客一样:
Awaitility.await().pollDelay(Durations.ONE_SECOND).until(() -> true);
这在概念上是不正确的,但它与Thread.sleep(1000)
相同。当然,最好的方法是用适当的条件传递Callable,而不是我所拥有的
true
。https://github.com/awaitility/awaitility
cu6pst1q4#
您可以使用java.util.concurrent.TimeUnit库,它在内部使用Thread. sleep。语法应该如下所示:
此库为时间单位提供了更清晰解释您可以使用'HOURS'/'MINUTES'/'SECONDS'
h9a6wy2h5#
如果在一个测试中绝对必须生成延迟
CountDownLatch
是一个简单的解决方案.在你的测试类中声明:在需要的测试中:
也许没有必要说,但请记住,你应该保持等待时间小,而不是累积等待太多的地方。
jdgnovmf6#
您也可以使用
CountDownLatch
对象,如here所述。kuuvgm7e7#
Mockito(已经通过Sping Boot 项目的可传递依赖项提供)有几种方法来等待异步事件,分别是发生的条件。
一个目前非常适合我们的简单模式是:
在this article(作者:@ fernando-cejas)中描述了两个稍微复杂但更为复杂的
我的紧急建议,关于目前的热门答案给在这里:您希望您的测试
1.尽快完成
1.具有一致的结果,与测试环境无关(非“片状”)
...所以不要在测试代码中使用
Thread.sleep()
。相反,让您的产品代码使用依赖注入(或者,稍微“脏一点”,公开一些可模仿/可监视的方法),然后使用Mockito、Awaitly、ConcurrentUnit或其他方法来确保在Assert发生之前满足异步前提条件。
z2acfund8#
还有一个普遍的问题:模拟时间是很困难的,而且,在单元测试中放置长时间运行/等待的代码也是很糟糕的做法。
因此,为了使调度API可测试,我使用了一个接口,它包含一真实的和一个模拟的实现,如下所示:
这样,您就可以在测试中模拟时间:
当然,针对
Clock
的高级多线程模拟要复杂得多,但是您可以使用ThreadLocal
引用和良好的时间同步策略来实现它。pcrecxhr9#
在测试中使用Thread.sleep并不是一个好的做法。它会创建脆弱的测试,根据环境(“Passes on my machine!”)或负载的不同,这些测试可能会不可预测地失败。不要依赖于计时(使用mock)或使用Awaitility之类的库进行异步测试。
Dependency : testImplementation 'org.awaitility:awaitility:3.0.0'