views:

307

answers:

3

What are the recommended approaches to using Thread.sleep() to speed up tests.

I am testing a network library with a retry functionality when connections are dropped or timeout errors occur, etc. The library however, uses a Thread.sleep() between the retries (so it won't connect thousands times while the server is restarting). The call is slowing the unit tests significantly, and I wonder what the options are to override it.

Note, I'm open to actually changing the code, or using a mocking framework to mock Thread.sleep(), but would like to hear your opinions/recommendation first.

+1  A: 

Make the sleeping time configurable through a setter, and provide a default value. So in your unit tests, call the setter with a small argument (1 for example), and then execute the method that would call Thread.sleep().

Another similar approach is to make if configurable via a boolean, so that Thread.sleep() isn't called at all if the boolean is set to false.

Bozho
+2  A: 

Create some retry delay type that represents the policy for retry delays. Invoke some method on the policy type for the delay. Mock it as you like. No conditional logic, or true/false flags. Just inject the type that you want.

In ConnectRetryPolicy.java

public interface ConnectRetryPolicy {
    void doRetryDelay();
}

In SleepConnectRetryPolicy.java

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);
        }
    }
}

In MockConnectRetryPolicy.java

public final class MockConnectRetryPolicy implements ConnectRetryPolicy {    
    @Override
    public void doRetryDelay() {
        // no delay
    }
}
Greg Mattes
This is not just a policy, but a configurable sleep executor. A policy would only represent the strategy around sleeping, not execute it. For the rest, sound idea.
Adriaan Koster
+4  A: 

It is usually a good idea to delegate time-related functionality to a separate component. That include getting the current time, as well as delays like Thread.sleep(). This way it is easy to substitute this component with mock during testing, as well as switch to a different implementation.

Eugene Kuleshov
I've been tempted to create a `Machine` class to abstract away all of that.
notnoop
Way to go. This way you can also set your configuration or even skip anything you want in just one place, rather then spreading this logic trough the code.
Eugene Kuleshov