Testing time-dependent logic in Java

It’s astounding. Time is… fleeting (The Rocky Horror Picture Show)

Testing time-sensitive business logic is essentially about being able to change the current time in our tests – somehow – and then checking how this affects the behaviour of the domain object being tested.

The primitive and brute-force way to do this is to manipulate the computer system clock by manually changing the current time prior to each test…  Crucially this approach does not lend itself to running as part of an automated test suite, for obvious reasons.
The other (better) way is use two different clocks: the production code can rely on the system clock while the tests code will depend on a custom clock, i.e is a clock which can be setup to return any particular time as the current time. Usually this custom clock will expose methods to advance/rewind the clock to specific points in time.
interface clock{
   public DateTime now();
}

class SystemClock implements Clock{
   public DateTime now(){
      return new DateTime();
   }
}

class CustomClock implements Clock{
   private DateTime now;
   public CustomClock(DateTime now){
      this.now = now;
   }
   public DateTime now(){
      return now;
   }
   public void tick(){
      now = now.plusDays(1);
   }
}

Both clocks realize the “now()” method defined in the Clock interface. The difference being that the now() method from SystemClock is a simple wrapper around a new instance of a Joda dateTime instance, while the now() method from the CustomClock returns a dateTime attribute which can be modified through the tick() method to make time pass faster :)The custom clock will be injected as a dependency of the testing code and the system clock as a dependency of the production code.

For a (somewhat contrived) example of how this plays out check out: https://github.com/eleco/customclock

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s