JUnit测试用例中的Thread.sleep

Pie*_*llo 5 java junit

我正在编写测试用例来测试对象行为.

当对象被实例化时,它必须允许调用方法,只有在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();
}
Run Code Online (Sandbox Code Playgroud)

你认为这是一种好习惯还是我应该采用另一种方法?

非常感谢

Thi*_*ler 9

在测试用例中使用(实际)时间有两个问题:

  1. 它从来都不是确定性的.特别是当您正在寻找高精度时,测试用例将在95%的时间内成功.但有时它们会失败,这些是最难调试的类型.请注意,Thread.sleep()在多线程测试用例中使用时,这更加困难.
  2. 有睡眠的测试用例需要很长时间才能运行,过了一段时间这将使运行完整的测试集变得麻烦.

如果必须,你的方式是可以接受的.但还有其他选择:

不要使用真正的时钟.而是使用可以从测试用例控制的假(模拟/存根)时钟:

@Test(expected = IllegalStateException.class)
public void testCallAfterTimeout() {
    MyObject o= new MyObject();
    // Example function that you could make
    advanceClock(1000, TimeUnit.MILLISECONDS)
    o.call();
}
Run Code Online (Sandbox Code Playgroud)

在你的对象中你必须注入一个时钟.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.
     }
} 
Run Code Online (Sandbox Code Playgroud)

在Java 8中,提供了用于此的机制,例如参见LocalDate.now().但你也可以轻松实现自己的安静.