我正在写一个测试用例来测试一个对象的行为。
当对象被示例化时,它必须允许调用一个方法,比如说call(),只有在500 ms内被调用,否则它必须抛出一个异常。
我设计的Junit测试用例是这样的:
@Test(expected = IllegalStateException.class)
public void testCallAfterTimeout() {
MyObject o= new MyObject();
//To ensure the timeout is occurred
Thread.sleep(1000);
o.call();
}
字符串
你认为这是一个很好的做法,还是我应该遵循另一种方法?
非常感谢
2条答案
按热度按时间u0sqgete1#
在测试用例中使用(真实的)时间有两个问题:
1.它从来都不是真正确定的。特别是当你在寻找高精度时,测试用例将在95%的时间内成功。但有时它们会失败,这些是最难调试的失败类型。请注意,当在多线程测试用例中使用
Thread.sleep()
时,这甚至更加困难。1.带有睡眠的测试用例需要很长时间才能运行,一段时间后,这将使运行完整的测试集变得很麻烦。
如果你必须这么做,你的方式也可以接受。但还有其他选择:
不要使用一个真实的时钟,而是使用一个你可以从测试用例中控制的假时钟:
字符串
在你的对象中,你必须注入一个时钟。
MyObject
可能看起来像这样:型
在Java 8中提供了一种机制,例如
LocalDate.now()
。但你也可以很容易地实现自己的机制。gmol16392#
不管这是什么意思,你是在自找麻烦......
如果你决定超时需要在60分钟后发生,你会等你的测试一个小时吗?超时应该是你的MyObject的参数,这样你就可以设置它为一些小的值进行测试(或者甚至设置为0来强制测试时总是超时)。
其次,如果你想真正拥有可测试的时间相关函数,时间和超时应该与你的主逻辑分开处理(MyObject类)。例如,您可以让Timekeeper类具有由MyObject类调用的方法canCallMethod()(它是建立在它的结构上的)。这样在你的测试中,您可以使用自己的Timekeeper实现初始化MyObject类,该实现返回true或false,并验证MyObject类的行为是否符合预期。MyObject可以具有始终使用“真实的”计时的默认构造函数,以便外部世界不是强迫你去对付时间守护者内部的人