Joda Time has a nice DateTimeUtils.setCurrentMillisFixed() to mock time.
It\'s very practical in tests.
Is there an equivalent in Java 8\'s java.time API
Joda Time is sure nice (thank you Stephen, Brian, you've made our world a better place) but I wasn't allowed to use it.
After some experimenting, I eventually came up with a way to mock time to a specific date in Java 8's java.time API with EasyMock
Here's what needs to be done:
Add a new java.time.Clock attribute to the tested class MyService and make sure the new attribute will be initialized properly at default values with an instantiation block or a constructor:
import java.time.Clock;
import java.time.LocalDateTime;
public class MyService {
// (...)
private Clock clock;
public Clock getClock() { return clock; }
public void setClock(Clock newClock) { clock = newClock; }
public void initDefaultClock() {
setClock(
Clock.system(
Clock.systemDefaultZone().getZone()
// You can just as well use
// java.util.TimeZone.getDefault().toZoneId() instead
)
);
}
{ initDefaultClock(); } // initialisation in an instantiation block, but
// it can be done in a constructor just as well
// (...)
}
Inject the new attribute clock into the method which calls for a current date-time. For instance, in my case I had to perform a check of whether a date stored in database happened before LocalDateTime.now(), which I replaced with LocalDateTime.now(clock), like so:
import java.time.Clock;
import java.time.LocalDateTime;
public class MyService {
// (...)
protected void doExecute() {
LocalDateTime dateToBeCompared = someLogic.whichReturns().aDate().fromDB();
while (dateToBeCompared.isBefore(LocalDateTime.now(clock))) {
someOtherLogic();
}
}
// (...)
}
In the test class, create a mock clock object and inject it into the tested class's instance just before you call the tested method doExecute(), then reset it back right afterwards, like so:
import java.time.Clock;
import java.time.LocalDateTime;
import java.time.OffsetDateTime;
import org.junit.Test;
public class MyServiceTest {
// (...)
private int year = 2017; // Be this a specific
private int month = 2; // date we need
private int day = 3; // to simulate.
@Test
public void doExecuteTest() throws Exception {
// (...) EasyMock stuff like mock(..), expect(..), replay(..) and whatnot
MyService myService = new MyService();
Clock mockClock =
Clock.fixed(
LocalDateTime.of(year, month, day, 0, 0).toInstant(OffsetDateTime.now().getOffset()),
Clock.systemDefaultZone().getZone() // or java.util.TimeZone.getDefault().toZoneId()
);
myService.setClock(mockClock); // set it before calling the tested method
myService.doExecute(); // calling tested method
myService.initDefaultClock(); // reset the clock to default right afterwards with our own previously created method
// (...) remaining EasyMock stuff: verify(..) and assertEquals(..)
}
}
Check it in debug mode and you will see the date of 2017 Feb 3 has been correctly injected into myService instance and used in the comparison instruction, and then has been properly reset to current date with initDefaultClock().