Recommended reading before you read this article: Fest assertions, Testing time dependant functionalities .
Do NOT do this!
I would like to present an example of an attempt to test time dependant functionality in a not very nice in my opinion way. Please see testing time dependant functionalities for the recommended way.
Below I present two very similar ways of trying to test drive time dependant functionalities. Please remember that the recommended way it to introduce a clock class.
Approach by extending Fest (DO NOT DO THIS)
1 2 3 4 5 6 7 8 9 |
// a poor attempt to test time dependant functionality by writing a Fest matcher @Test public void marksReportAsComplete() { report.markAsComplete(); assertTrue(report.isComplete()); // DO NOT DO THIS :( assertThatDate(report.completedOn()).isWithinSecondOfNow(); } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
/** * DO NOT DO THIS :( */ public class DateRangeAssertion implements AssertExtension { private Date actualDate; public DateRangeAssertion(Date actualDate) { this.actualDate = actualDate; } public static DateRangeAssertion assertThatDate(Date date) { return new DateRangeAssertion(date); } public DateRangeAssertion isWithinSecondOfNow() { Date now = new Date(); long differenceInMiliseconds = Math.abs(actualDate.getTime() - now.getTime()); assertThat(differenceInMiliseconds).isLessThanOrEqualTo(1000L); return this; } } |
Approach by extending Hamcrest (DO NOT DO THIS)
1 2 3 4 5 6 7 8 9 |
// a poor attempt to test time dependant functionality by writing a Hamcrest matcher @Test public void marksReportAsComplete2() { report.markAsComplete(); assertTrue(report.isComplete()); // DO NOT DO THIS :( assertThat(report.completedOn(), isWithinOneSecondOfNow()); } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
/** * DO NOT DO THIS :( */ public class HamcrestMatchers { public static TypeSafeMatcher isWithinOneSecondOfNow() { return new TypeSafeMatcher() { private Date now; public boolean matchesSafely(Date actualDate) { now = new Date(); long differenceInMiliseconds = Math.abs(actualDate.getTime() - now.getTime()); return differenceInMiliseconds < 1000L; } public void describeTo(Description description) { description.appendText("a date within a second of " + now); } }; } } |
Why avoid this approach?
Think about it. Is “is within one second” actually what you are looking for? Probably not. You are looking for “is now”.
The other argument is that is reduces readability.