Steve Freeman showed a neat unit testing trick at JAX/DevCon London last month, that was not mentioned in his and Nat Pryce’s great book on TDD. His presentation was mostly on getting more out of unit tests by making it easier to read the tests and understand errors. One of the problems he talked about was the confusion that date values can cause in error reports.
For example, this test result makes people spend time on investigating what exactly went wrong:
java.lang.AssertionError: expected:<Tue Dec 01 03:04:05 GMT 2020>
but was:<Thu Dec 03 04:05:00 GMT 2015>
at org.junit.Assert.fail(Assert.java:91)
at org.junit.Assert.failNotEquals(Assert.java:645)
at org.junit.Assert.assertEquals(Assert.java:126)
at org.junit.Assert.assertEquals(Assert.java:145)
at datetest.FirstTest.checkDates(FirstTest.java:34)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
The problem here is that arbitrary dates are meaninless and it takes a lot of time to understand what went wrong. His solution is to override toString in the dates and give the objects meaningful names.
@Test
public void checkDatesBetter(){
SystemUnderTest sut=new SystemUnderTest();
sut.setStartDate(namedDate("Start Date",new Date(110,11,1,3,4,5)));
Date endDate=namedDate("End Date",new Date(120,11,1,3,4,5));
sut.setEndDate(endDate);
sut.setProcessDate(namedDate("Process Date",new Date(115,11,3,4,5)));
assertEquals(endDate, sut.runSomeWeirdDateCalculation());
}
private Date namedDate(final String name, final Date date) {
return new Date(date.getTime()){
@Override
public String toString() {
return name;
}
};
}
When a test fails, JUnit will print out the name passed to toString. This makes it much easier to understand what failed:
java.lang.AssertionError: expected:<End Date> but was:<Process Date> at org.junit.Assert.fail(Assert.java:91) at org.junit.Assert.failNotEquals(Assert.java:645) at org.junit.Assert.assertEquals(Assert.java:126) at org.junit.Assert.assertEquals(Assert.java:145) at datetest.FirstTest.checkDatesBetter(FirstTest.java:44)


I’m sure we do mention it somewhere in the book. It is a cunning trick but unfortunately cannot be applied to final types.
Nice. But how about date formatting (SimpleDateFormat)?
For instance when I need just mm/dd/yyyy, not entire date. Overriding Date#toString() won’t help here.
My first thought was: is this trick possible in .NET? Unfortunately no, because .NET’s System.DateTime type is a struct, so it cannot be extended with an anonymous class. Here’s the link to the StackOverflow discussion that reached this conclusion: http://stackoverflow.com/questions/3990683/wicked-junit-date-trick-how-would-you-do-this-in-c