Java 使用Thread.sleep进行测试
使用Java 使用Thread.sleep进行测试,java,unit-testing,testing,sleep,Java,Unit Testing,Testing,Sleep,使用Thread.sleep()加速测试的推荐方法有哪些 我正在测试一个具有重试功能的网络库,当连接断开或出现超时错误时,等等。但是,该库在重试之间使用Thread.sleep()(因此在服务器重新启动时,它不会连接数千次)。这个调用大大降低了单元测试的速度,我想知道覆盖它的选项是什么 注意,我愿意实际更改代码,或者使用模拟框架来模拟Thread.sleep(),但希望先听听您的意见/建议。通过setter设置睡眠时间,并提供默认值。因此,在单元测试中,使用一个小参数(例如1)调用setter,
Thread.sleep()
加速测试的推荐方法有哪些
我正在测试一个具有重试功能的网络库,当连接断开或出现超时错误时,等等。但是,该库在重试之间使用Thread.sleep()
(因此在服务器重新启动时,它不会连接数千次)。这个调用大大降低了单元测试的速度,我想知道覆盖它的选项是什么
注意,我愿意实际更改代码,或者使用模拟框架来模拟Thread.sleep(),但希望先听听您的意见/建议。通过setter设置睡眠时间,并提供默认值。因此,在单元测试中,使用一个小参数(例如1)调用setter,然后执行调用
Thread.sleep()
的方法
另一种类似的方法是通过布尔值使if可配置,这样,如果
布尔值设置为false
,则根本不会调用Thread.sleep()
,创建一些表示重试延迟策略的重试延迟类型。为延迟调用策略类型上的某些方法。随便你怎么嘲笑。无条件逻辑或true
/false
标志。只需注入您想要的类型
在ConnectRetryPolicy.java中
public interface ConnectRetryPolicy {
void doRetryDelay();
}
public class final SleepConnectRetryPolicy implements ConnectRetryPolicy {
private final int delay;
public SleepConnectRetryPolicy(final int delay) {
this.delay = delay;
}
@Override
public void doRetryDelay() {
try {
Thread.sleep(delay);
} catch (InterruptedException ie) {
log.error("connection delay sleep interrupted", ie);
}
}
}
public final class MockConnectRetryPolicy implements ConnectRetryPolicy {
@Override
public void doRetryDelay() {
// no delay
}
}
在SleepConnectRetryPolicy.java中
public interface ConnectRetryPolicy {
void doRetryDelay();
}
public class final SleepConnectRetryPolicy implements ConnectRetryPolicy {
private final int delay;
public SleepConnectRetryPolicy(final int delay) {
this.delay = delay;
}
@Override
public void doRetryDelay() {
try {
Thread.sleep(delay);
} catch (InterruptedException ie) {
log.error("connection delay sleep interrupted", ie);
}
}
}
public final class MockConnectRetryPolicy implements ConnectRetryPolicy {
@Override
public void doRetryDelay() {
// no delay
}
}
在MockConnectRetryPolicy.java中
public interface ConnectRetryPolicy {
void doRetryDelay();
}
public class final SleepConnectRetryPolicy implements ConnectRetryPolicy {
private final int delay;
public SleepConnectRetryPolicy(final int delay) {
this.delay = delay;
}
@Override
public void doRetryDelay() {
try {
Thread.sleep(delay);
} catch (InterruptedException ie) {
log.error("connection delay sleep interrupted", ie);
}
}
}
public final class MockConnectRetryPolicy implements ConnectRetryPolicy {
@Override
public void doRetryDelay() {
// no delay
}
}
将与时间相关的功能委托给单独的组件通常是一个好主意。这包括获取当前时间,以及诸如Thread.sleep()之类的延迟。通过这种方式,在测试期间可以很容易地用mock替换此组件,并切换到其他实现。Eugene是对的,制作您自己的组件来包装您无法控制的系统刚才我自己做了这件事,我想与大家分享一下,这就是所谓的“检查一下:
Generator
是一个类,当您调用getId()
时,它返回当前系统时间
public class GeneratorTests implements SystemTime {
private Generator cut;
private long currentSystemTime;
@Before
public void setup(){
cut = Generator.getInstance(this);
}
@Test
public void testGetId_returnedUniqueId(){
currentSystemTime = 123;
String id = cut.getId();
assertTrue(id.equals("123"));
}
@Override
public long currentTimeMillis() {
return currentSystemTime;
}
}
我们使测试类成为“自分流”,并成为系统时间组件,这样我们就可以完全控制时间
public class BlundellSystemTime implements SystemTime {
@Override
public long currentTimeMillis(){
return System.currentTimeMillis();
}
}
我们包装不在我们控制之下的组件
public interface SystemTime {
long currentTimeMillis();
}
然后制作一个接口,这样我们的测试就可以“自分流”我想问一下为什么要测试Thread.sleep。似乎是我,你试图测试某个事件的后果
i、 e.如果:
- 连接超时
- 断开连接
如果您基于事件对代码进行建模,那么您可以测试在发生特定事件时应该发生什么,而不必提出屏蔽并发API调用的构造。你到底在测试什么?您是在测试应用程序对不同刺激的反应,还是只是测试JVM是否正常工作
我同意其他读者的观点,即有时在任何代码时间或线程相关的时间(即虚拟时钟)周围放置一个抽象是有用的,这样您就可以模拟任何计时/并发行为,并专注于单元本身的行为
听起来您还应该采用一种状态模式,以便根据对象所处的状态,对象具有特定的行为。i、 e等待连接状态,连接状态。转换到不同的状态将通过不同的事件进行,例如超时、断开连接等。不确定这是否满足您的需要,但它肯定会删除许多条件逻辑,从而使代码更加复杂和不清楚
如果您采用这种方法,那么您仍然可以在单元级别测试行为,同时仍然可以稍后通过集成测试或验收测试进行现场测试 我刚刚遇到了一个类似的问题,我创建了一个Sleeper
接口来抽象这个问题:
public interface Sleeper
{
void sleep( long millis ) throws InterruptedException;
}
默认实现使用Thread.sleep()
:
在我的单元测试中,我注入了一个FixedDateTimeAdvanceSleeper
:
public class FixedDateTimeAdvanceSleeper implements Sleeper
{
@Override
public void sleep( long millis ) throws InterruptedException
{
DateTimeUtils.setCurrentMillisFixed( DateTime.now().getMillis() + millis );
}
}
这允许我查询单元测试中的时间:
assertThat( new DateTime( DateTimeUtils.currentTimeMillis() ) ).isEqualTo( new DateTime( "2014-03-27T00:00:30" ) );
请注意,您需要首先使用DateTimeUtils.setCurrentMillisFixed(new DateTime(“2014-03-26T09:37:13”).getMillis()修复时间在测试开始时编写>并使用DateTimeUtils.setCurrentMillisSystem()在测试后再次恢复时间代码>我一直想创建一个机器
类来抽象掉所有这些。通过这种方式,您还可以在一个地方设置配置,甚至可以跳过任何您想要的内容,而不是通过代码传播这种逻辑。@notnoop正是我使用时钟
类所做的。支持基本操作,如Clock.now()
,Clock.freeze()
,Clock.freeze(pointInTime)
等。没有组件直接与运行时交互以获取时间,而是通过时钟
。这可以看作是模拟单元测试的案例研究。不要使用Thread.sleep(),使用wait()方法。Thread.sleep()使用CPU周期,而wait()不使用。这不仅仅是一个策略,而是一个可配置的睡眠执行器。策略只代表围绕睡眠的策略,而不是执行它。对于其余部分,这是一个好主意。如果我不想为了测试而将我的内部配置暴露给外部,该怎么办?