Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In Grails, is there a good way to mock the current time using Joda time?

I'm writing some code that does date and time calculations against the current time. In Joda time, this is accessed through a (Java) constructor, as it is an immutable object. I need to be able to mock so that new DateTime() returns a specific constant instant so I can do sensible test assertions, but leave all other DateTime methods alone.

This is proving nasty. Grails mockFor(DateTime, true) won't let me mock a Java constructor, yet there is no obvious or readable non-constructor way of getting the time in Joda time.

The only available options seem to involve low-level JVM techniques like JMockit or EasyMock 3 class mocking, which are a pain from Grails. Is there a simple/straightforward way to achieve this?

like image 434
Stuart Watt Avatar asked May 25 '11 20:05

Stuart Watt


People also ask

Is Joda time deprecated?

So the short answer to your question is: YES (deprecated).

What is Jodatime?

Joda-Time is an API created by joda.org which offers better classes and having efficient methods to handle date and time than classes from java. util package like Calendar, Gregorian Calendar, Date, etc. This API is included in Java 8.0 with the java.

How do you mock a timestamp in Java?

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); sdf. setTimeZone(TimeZone. getTimeZone("PST")); Date NOW = sdf. parse("2019-02-11 00:00:00"); Timestamp time=new Timestamp(NOW.


2 Answers

I know this as already been accepted, but with Joda-time you can freeze and set it to be whatever you like. So you can freeze time, advance time, go backwards in time. Provided you're using Joda consistently, your objects will get "now" as whatever time you've set that to be.

// Stop time (and set a particular point in time):
DateTimeUtils.setCurrentMillisFixed(whenever);

// Advance time by the offset:
DateTimeUtils.setCurrentMillisOffset(offsetFromCurrent);

// Restore time (you could do this in an @After method)
DateTimeUtils.setCurrentMillisSystem();
like image 73
alpian Avatar answered Oct 28 '22 05:10

alpian


We ended up creating dateService with now() method. In unit tests we mock it with

domainInstance.dateService = [ now: { currentTime } ] as DateService

where currentTime is a unit test class field. This imposes everybody's dependency on dateService (our only nearly-global dependency), and for src classes one has to pass it by hand.

Unit tests, OTOH, look pretty clear with it.

like image 23
Victor Sergienko Avatar answered Oct 28 '22 07:10

Victor Sergienko