In my code I have something like this:
private void doSomething() {
Calendar today = Calendar.getInstance();
....
}
How can I "mock" it in my junit test to return a specific date?
In my code I have something like this:
private void doSomething() {
Calendar today = Calendar.getInstance();
....
}
How can I "mock" it in my junit test to return a specific date?
As far as I see it you have three sensible options:
Inject the Calendar
instance in whatever method/class you set that day in.
private void method(final Calendar cal)
{
Date today = cal.getTime();
}
Use JodaTime instead of Calendar
. This is less an option and more a case of a suggestion as JodaTime will make your life a lot easier. You will still need to inject this time in to the method.
DateTime dt = new DateTime();
Date jdkDate = dt.toDate();
Wrap Calendar
inside some interface that allows you to fetch the time. You then just mock that interface and get it to return a constant Date
.
Date today = calendarInterfaceInstance.getCurrentDate()
DateTimeUtils
class has static methods that set the current time for all other Joda Time objects. This is very useful to set the time to a certain moment, for example for testing. –
Busby You can mock it using PowerMock in combination with Mockito:
On top of your class:
@RunWith(PowerMockRunner.class)
@PrepareForTest({ClassThatCallsTheCalendar.class})
The key to success is that you have to put the class where you use Calendar in PrepareForTest instead of Calendar itself because it is a system class. (I personally had to search a lot before I found this)
Then the mocking itself:
mockStatic(Calendar.class);
when(Calendar.getInstance()).thenReturn(calendar);
PowerMockito.whenNew(Calendar.getInstance()).withAnyArguments().thenReturn(MY_INSTANCE_OBJECT_TO_FEED);
–
Prudential As far as I see it you have three sensible options:
Inject the Calendar
instance in whatever method/class you set that day in.
private void method(final Calendar cal)
{
Date today = cal.getTime();
}
Use JodaTime instead of Calendar
. This is less an option and more a case of a suggestion as JodaTime will make your life a lot easier. You will still need to inject this time in to the method.
DateTime dt = new DateTime();
Date jdkDate = dt.toDate();
Wrap Calendar
inside some interface that allows you to fetch the time. You then just mock that interface and get it to return a constant Date
.
Date today = calendarInterfaceInstance.getCurrentDate()
DateTimeUtils
class has static methods that set the current time for all other Joda Time objects. This is very useful to set the time to a certain moment, for example for testing. –
Busby Don't mock it - instead introduce a method you can mock that gets dates. Something like this:
interface Utility {
Date getDate();
}
Utilities implements Utility {
public Date getDate() {
return Calendar.getInstance().getTime();
}
}
Then you can inject this into your class or just use a helper class with a bunch of static methods with a load method for the interface:
public class AppUtil {
private static Utility util = new Utilities();
public static void load(Utility newUtil) {
this.util = newUtil;
}
public static Date getDate() {
return util.getDate();
}
}
Then in your application code:
private void doSomething() {
Date today = AppUtil.getDate();
....
}
You can then just load a mock interface in your test methods.
@Test
public void shouldDoSomethingUseful() {
Utility mockUtility = // .. create mock here
AppUtil.load(mockUtility);
// .. set up your expectations
// exercise the functionality
classUnderTest.doSomethingViaAPI();
// ... maybe assert something
}
See also Should you only mock types you own? and Test smell - everything is mocked
Using Mockito and PowerMockito:
Calendar endOfMarch = Calendar.getInstance();
endOfMarch.set(2011, Calendar.MARCH, 27);
PowerMockito.mockStatic(Calendar.class);
Mockito.when(Calendar.getInstance()).thenReturn(endOfMarch);
Refer to the link for the complete code.
Write a class called DateHelper
with a method getCalendar
that returns Calendar.getInstance()
. Refactor the class that you're testing so that it has a member variable of type DateHelper
, and a constructor that injects that member variable. Use that constructor in your test, to inject a mock of DateHelper
, in which getCalendar
has been stubbed to return some known date.
With Mockk
private lateinit var calendar: Calendar
@Before
fun setup() {
calendar = mockk(relaxed = true)
mockkStatic(Calendar::class)
every { Calendar.getInstance() } returns calendar
}
@Test
fun `test date when date is less than 16 month is 0`() {
every { calendar[Calendar.DAY_OF_MONTH] } returns 12
every { calendar[Calendar.MONTH] } returns 0
every { calendar[Calendar.YEAR] } returns 2023
// assert here
}
refer to the link for mockk documentation
Calendar
class. It was a mostly failed attempt to make up for the deficiencies of Date
and was always cumbersome to work with. Both Date
and Calendar
were obsoleted with the release of java.time, the modern Java date and time API, nearly 10 years ago. Among many features java.time comes with the possibility of supplying a clock that you control to the methods that obtain the current time, so you don’t need mocking at all. –
Lietuva dates
and thus the good old Calendar :'( –
Lessard You can mockit using JMockit. Here you can see how you can do it: Mock Java Calendar - JMockit vs Mockito.
You can do that as follows using Junit 5 and Mockito
@Test
public void doSomething() {
listCalendarParams("now", Calendar.getInstance());
Calendar fakedCalendar = new GregorianCalendar(2023, Calendar.OCTOBER, 15, 10, 15);
listCalendarParams("mock", fakedCalendar);
try (MockedStatic<Calendar> mockedStatic = Mockito.mockStatic(Calendar.class, Mockito.CALLS_REAL_METHODS)) {
mockedStatic.when(Calendar::getInstance).thenReturn(fakedCalendar);
//This or any method here using Calendar.getInstance() will be replaced by mock defined above
Calendar calendar = Calendar.getInstance();
listCalendarParams("evaluated", calendar);
assertEquals(Calendar.OCTOBER, calendar.get(Calendar.MONTH));
assertEquals(15, calendar.get(Calendar.DAY_OF_MONTH));
assertEquals(10, calendar.get(Calendar.HOUR_OF_DAY));
assertEquals(15, calendar.get(Calendar.MINUTE));
}
}
private static void listCalendarParams(String nameOfCal, Calendar calendar) {
System.out.println(nameOfCal + ":\t" +
new SimpleDateFormat("yyyy'-'MM'-'dd'T'HH':'mm':'ss")
.format(calendar.getTime()));
}3
Output:
now: 2023-11-27T14:00:48 //This will change anytime you run it.
mock: 2023-10-15T10:15:00
evaluated: 2023-10-15T10:15:00
Avoid use Calendar.getInstance()
and just use Mockito
methods to return what you like.
For example:
@Test
fun italianLocale_returnsItalianFormatDate() {
val calendar: Calendar = Mockito.mock(Calendar::class.java)
Mockito.`when`(calendar.get(Calendar.DAY_OF_MONTH)).thenReturn(27)
Mockito.`when`(calendar.get(Calendar.YEAR)).thenReturn(2023)
Mockito.`when`(calendar.get(Calendar.MONTH)).thenReturn(1)
val formatted = calendar.toReadableDate()
assert(formatted == "27/01/2023")
}
import Mockito in your gradle file with:
testImplementation ("org.mockito.kotlin:mockito-kotlin:x.x.x")
or (if you are using groovy)
testImplementation "org.mockito.kotlin:mockito-kotlin:x.x.x"
© 2022 - 2025 — McMap. All rights reserved.
today
a class member (field) or a local variable inside a method? – EnunciateCalendar
class was years ago supplanted by the modern java.time classes defined in JSR 310. – Asarestatic
methods on thejava.time.Clock
class. Pass the fakedClock
instance to the various methods on variousjava.time.*
classes. – Asare