I understand that you cannot change the method that you need to test. Unfortunately this also means that you are stuck with the old and often not very programmer-friendly Date
class (I am assuming java.util.Date
).
Edit: The no-arg Date
constructor that your method uses in turn uses System.currentTimeMillis()
, a static native method. I didn’t know there were tools that could mock contructors and static native methods, but was informed by comment and answer by @Rogério, the developer of JMockit, that such mocking tools exist.
In any case, there is an alternative: you calculate some number of days from today, pass the resulting Date
to the method and check that you get the number back you used in your calculation. This will work on any day and requires no mocking/stubbing.
In the code below I am assuming that the getDaysUntil
method should discard the hours and minutes and just look at the date in the computer’s time zone. If the real requirements differ, you can probably make the appropriate adjustments to my code.
We want to take into account that the method may run over midnight. If so, I consider the result undefined since we do not know whether the Date
object was constructed before or after midnight. In this case I simply try again, assuming the test will finish before the next midnight.
@Test
public void testGetDaysUntil() {
A instanceUnderTest = new A();
for (int daysToTest = 0; daysToTest <= 400; daysToTest++) {
LocalDate today;
int result;
do {
today = LocalDate.now(); // do this in each iteration in case day changes underway
LocalDate targetDate = today.plusDays(daysToTest);
Date midnightAtStartOfDay = Date.from(targetDate.atStartOfDay(ZoneId.systemDefault())
.toInstant());
result = instanceUnderTest.getDaysUntil(midnightAtStartOfDay);
} while (! today.equals(LocalDate.now())); // if we have passed midnight, try again
assertEquals(daysToTest, result);
do {
today = LocalDate.now();
LocalDate targetDate = today.plusDays(daysToTest);
Date nearMidnightAtEndOfDay = Date.from(targetDate.atTime(23, 59, 59, 400_000_000)
.atZone(ZoneId.systemDefault())
.toInstant());
result = instanceUnderTest.getDaysUntil(nearMidnightAtEndOfDay);
} while (! today.equals(LocalDate.now()));
assertEquals(daysToTest, result);
}
}
I have used the Java 8 classes for the date and time calculations. If you cannot use Java 8, Calendar
and/or GregorianCalendar
can be used, they may be just a little more cumbersome for this job, but at least can be converted to Date
easily.