Mocking Time

In many cases in our code we do something like that:

LocalDate today = LocalDate.now();

The problem is that your tests then needs to work based on the real current date (or time, or zone date time, whatever).

Sometime it’s fine, sometimes the test fails randomly. At end of day, month or year in particular. It also forces you to calculated the expected result instead of using a constant.

In the new Java date/time API, there is a built-in way to set a constant time called a Clock.

So instead of the code above, you do

Clock clock = ;
LocalDate today = LocalDate.now(clock);

Clock is an interface with multiple implementations.

If you want a real clock, you can do this.

Clock clock = Clock.systemDefaultZone();
Clock clock = Clock.systemUTC();
Clock clock = Clock.system(ZoneId.systemDefault());

But it you want a fake clock during your test, you can do this:

Clock clock = Clock.fixed(instant, ZoneOffset.UTC);

Sadly, I must confess, since the clock is using an Instant, it’s a bit more complicated to initialize then I would like. For example, to put it to a specific day, you do that:

LocalDate today = LocalDate.ofYearDay(2019, 200);
Clock clock = Clock.fixed(today.atStartOfDay().toInstant(ZoneOffset.UTC), ZoneOffset.UTC);

There are methods to make the clock tick or move forward. However, it’s an immutable class, so ticking the clock will return a new clock. Nothing prevents you from doing your own MutableClock. Here is an implementation.

public class MutableClock extends Clock {

  private volatile Instant now;
  private final ZoneId zone;

  public MutableClock() {
    this(Instant.now());
  }
  
  public MutableClock(Instant now) {
    this(now, ZoneId.systemDefault());
  }

  public MutableClock(Instant now, ZoneId zone) {
    this.now = now;
    this.zone = zone;
  }

  @Override
  public ZoneId getZone() {
    return zone;
  }

  @Override
  public Clock withZone(ZoneId zone) {
    return new MutableClock(now, zone);
  }

  @Override
  public Instant instant() {
    return now;
  }

  public synchronized void plus(TemporalAmount amount) {
    now = now.plus(amount);
  }
}

I found it a really useful tool to fix existing code in a class where you want the time to move at your own pace.

Happy clock mocking!