我正在编写测试用例以测试对象行为。
当对象被实例化时,它必须允许调用方法,只有在500毫秒内调用它时才调用call(),否则它必须抛出异常。
我设计了这样的Junit测试用例:
@Test(expected = IllegalStateException.class)
public void testCallAfterTimeout() {
MyObject o= new MyObject();
//To ensure the timeout is occurred
Thread.sleep(1000);
o.call();
}
你认为这是一种好习惯还是我应该采用另一种方法?
非常感谢
答案 0 :(得分:9)
在测试用例中使用(实际)时间有两个问题:
Thread.sleep()
时,这更加困难。如果必须,你的方式是可以接受的。但还有其他选择:
不要使用真正的时钟。而是使用可以从测试用例中控制的假(模拟/存根)时钟:
@Test(expected = IllegalStateException.class)
public void testCallAfterTimeout() {
MyObject o= new MyObject();
// Example function that you could make
advanceClock(1000, TimeUnit.MILLISECONDS)
o.call();
}
在你的对象中你必须注入一个时钟。 MyObject
可能如下所示:
class MyObject
{
public MyObject()
{
this(new Clock());
}
// Protected so only the test case can access it
protected MyObject(Clock clock)
{
// Save clock as local variable, store creation time etc.
}
}
在Java 8中提供了一种机制,例如参见LocalDate.now()
。但你也可以轻松实现自己的安静。
答案 1 :(得分:1)
无论有什么意义,你都在寻找麻烦......
如果您决定在60分钟后需要超时,您会等待一小时的测试吗? 超时应该是MyObject的参数,因此您可以将其设置为一些较小的值进行测试(甚至0以在测试时强制alwyas超时)。
其次,如果你想真正拥有可测试的时间相关函数,那么时间和超时应该与你的主逻辑(MyObject类)分开处理。例如,你可以使用mehtod canCallMethod()的Timekeeper类,它由你的MyObject类调用(并且在它的构造时设置)。以这种方式在测试中,使用自己的Timekeeper实现初始化MyObject类,该实现返回true或false,并验证MyObject类的行为是否符合预期。 MyObject可以使用默认构造函数,它始终使用“真实”时间戳,因此外部世界不会强制处理Timekeeper内部。