I have a JUnit test that fails because the milliseconds are different. In this case I don\'t care about the milliseconds. How can I change the precision of the assert to i
Using JUnit 4 you could also implement a matcher for testing dates according to your chosen precision. In this example the matcher takes a string format expression as a parameter. The code is not any shorter for this example. However the matcher class may be reused; and if you give it a describing name you can document the intention with the test in an elegant way.
import static org.junit.Assert.assertThat;
// further imports from org.junit. and org.hamcrest.
@Test
public void testAddEventsToBaby() {
Date referenceDate = new Date();
// Do something..
Date testDate = new Date();
//assertThat(referenceDate, equalTo(testDate)); // Test on equal could fail; it is a race condition
assertThat(referenceDate, sameCalendarDay(testDate, "yyyy MM dd"));
}
public static Matcher<Date> sameCalendarDay(final Object testValue, final String dateFormat){
final SimpleDateFormat formatter = new SimpleDateFormat(dateFormat);
return new BaseMatcher<Date>() {
protected Object theTestValue = testValue;
public boolean matches(Object theExpected) {
return formatter.format(theExpected).equals(formatter.format(theTestValue));
}
public void describeTo(Description description) {
description.appendText(theTestValue.toString());
}
};
}
Use a DateFormat object with a format that shows only the parts you want to match and do an assertEquals()
on the resulting Strings. You can also easily wrap that in your own assertDatesAlmostEqual()
method.
Yet another workaround, I'd do it like this:
assertTrue("Dates aren't close enough to each other!", (date2.getTime() - date1.getTime()) < 1000);
JUnit has a built in assertion for comparing doubles, and specifying how close they need to be. In this case, the delta is within how many milliseconds you consider dates equivalent. This solution has no boundary conditions, measures absolute variance, can easily specify precision, and requires no additional libraries or code to be written.
Date dateOne = new Date();
dateOne.setTime(61202516585000L);
Date dateTwo = new Date();
dateTwo.setTime(61202516585123L);
// this line passes correctly
Assert.assertEquals(dateOne.getTime(), dateTwo.getTime(), 500.0);
// this line fails correctly
Assert.assertEquals(dateOne.getTime(), dateTwo.getTime(), 100.0);
Note It must be 100.0 instead of 100 (or a cast to double is needed) to force it to compare them as doubles.
There are libraries that help with this:
Apache commons-lang
If you have Apache commons-lang on your classpath, you can use DateUtils.truncate to truncate the dates to some field.
assertEquals(DateUtils.truncate(date1,Calendar.SECOND),
DateUtils.truncate(date2,Calendar.SECOND));
There is a shorthand for this:
assertTrue(DateUtils.truncatedEquals(date1,date2,Calendar.SECOND));
Note that 12:00:00.001 and 11:59:00.999 would truncate to different values, so this might not be ideal. For that, there is round:
assertEquals(DateUtils.round(date1,Calendar.SECOND),
DateUtils.round(date2,Calendar.SECOND));
AssertJ
Starting with version 3.7.0, AssertJ added an isCloseTo assertions, if you are using the Java 8 Date / Time API.
LocalTime _07_10 = LocalTime.of(7, 10);
LocalTime _07_42 = LocalTime.of(7, 42);
assertThat(_07_10).isCloseTo(_07_42, within(1, ChronoUnit.HOURS));
assertThat(_07_10).isCloseTo(_07_42, within(32, ChronoUnit.MINUTES));
It also works with legacy java Dates as well:
Date d1 = new Date();
Date d2 = new Date();
assertThat(d1).isCloseTo(d2, within(100, ChronoUnit.MILLIS).getValue());
Something like this might work:
assertEquals(new SimpleDateFormat("dd MMM yyyy").format(dateOne),
new SimpleDateFormat("dd MMM yyyy").format(dateTwo));