This is what I am using. I found it in the book: Test Driven - Practical TDD and Acceptance TDD for Java Developers by Lasse Koskela.
public interface TimeSource {
long millis();
}
public class SystemTime {
private static TimeSource source = null;
private static final TimeSource DEFAULTSRC =
new TimeSource() {
public long millis() {
return System.currentTimeMillis();
}
};
private static TimeSource getTimeSource() {
TimeSource answer;
if (source == null) {
answer = DEFAULTSRC;
} else {
answer = source;
}
return answer;
}
public static void setTimeSource(final TimeSource timeSource) {
SystemTime.source = timeSource;
}
public static void reset() {
setTimeSource(null);
}
public static long asMillis() {
return getTimeSource().millis();
}
public static Date asDate() {
return new Date(asMillis());
}
}
Notice that the default time source, DEFAULTSRC, is System.currentTimeMillis(). It is replaced in unit tests; however, the normal behavior is the standard system time.
This is where it is used:
public class SimHengstler {
private long lastTime = 0;
public SimHengstler() {
lastTime = SystemTime.asMillis(); //System.currentTimeMillis();
}
}
And here is the unit test:
import com.company.timing.SystemTime;
import com.company.timing.TimeSource;
public class SimHengstlerTest {
@After
public void tearDown() {
SystemTime.reset();
}
@Test
public final void testComputeAccel() {
// Setup
setStartTime();
SimHengstler instance = new SimHengstler();
setEndTime(1020L);
}
private void setStartTime() {
final long fakeStartTime = 1000L;
SystemTime.setTimeSource(new TimeSource() {
public long millis() {
return fakeStartTime;
}
});
}
private void setEndTime(final long t) {
final long fakeEndTime = t; // 20 millisecond time difference
SystemTime.setTimeSource(new TimeSource() {
public long millis() {
return fakeEndTime;
}
});
}
In the unit test, I replaced the TimeSource with just a number which was set to 1000 milliseconds. That will serve as the starting time. When calling setEndTime(), I input 1020 milliseconds for the finishing time. This gave me a controlled 20 millisecond time difference.
There is no testing code in the production code, just getting the normal Systemtime.
Make sure to call reset after testing to get back to using the system time method rather than the faked time.