Search code examples
javajunit

Thread.sleep in JUnit test case


I'm writing a test case to test an object behaviour.

When the object is instantiated it must allow the call of a method let say call() only if it has been called within 500 ms, otherwise it must throw an exception.

I designed the Junit test case like this:

@Test(expected = IllegalStateException.class)
public void testCallAfterTimeout() {
    MyObject o= new MyObject();
    //To ensure the timeout is occurred
    Thread.sleep(1000);
    o.call();
}

Do you think is a good practice or I should follow another approach?

Many thanks


Solution

  • There are two problems with using (real) time in test cases:

    1. It is never really deterministic. Especially when you are looking for high precision, testcases will succeed 95% of the time. But sometimes they fail, these are the hardest types of failure to debug. Note that when using Thread.sleep() with in a multithreaded test case this is even more difficult.
    2. Test cases with sleeps take long to run, after a while this will make running your full testset cumbersome.

    If you must, your way is acceptable. But there are other options:

    Don't use a real clock. Instead use a fake (mocked/stubbed) clock that you can control from your testcase:

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

    In your object you have to inject a clock. MyObject could look like this:

    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.
         }
    } 
    

    In Java 8 a mechanism for this is provided, see for instance LocalDate.now(). But you can also implement your own quite easily.