One approach that works best for unit testing is to abstract the way the current time is accessed in your code.
Instead of calling System.currentTimeMillis() directly you can provide your own implementation.
Something like this (pseudo-code):
class MyTime {
private static TimeInterface CurrentTimeInterface = new DefaultTimeImpl();
public setTimeInterface(TimeInterface timeInterface) {
CurrentTimeInterface = timeInterface;
}
public int getTime() { CurrentTimeInterface.getTime(); }
}
class DefaultTimeImpl implements TimeInterface {
public int getTime() { return System.currentTimeMillis(); }
}
class TestTimeImpl implements TimeInterface {
private int CurrentTimeMillis = 0;
public int getTime() { return CurrentTimeMillis; }
public void setTime(int timeMillis) { CurrentTimeMillis = timeMillis}
public void sleep(int millis) { CurrentTimeMillis += millis; }
}
Then, everywhere you would have called System.getTimeMillis() instead call MyTime.getTime(). When you're testing your code simply create a TestTimeImpl and call MyTime.setTimeInterface(testTimeImpl). Then when you want time to advance call testTimeImpl.sleep() or testTimeImpl.setTime().
This allows you to simulate any time down to the millisecond.