The parameterless now()
factory methods of the key classes in the java.time
package implicitly use the system clock in the default time-zone.
In order to improve testability, there exists an overload now(Clock clock)
, which allows to inject a specified clock.
Using this method, tests of date/time related code become repeatable.
Refer to the documentation of java.time.Clock for more details.
Snippet of Noncompliant Code
final Instant instant = Instant.now(); // Noncompliant: implicitly depends on system clock
// [...] decisions or serialization based on the actual value of instant can't be tested reliably
final LocalDate today = LocalDate.now(); // Noncompliant
if (today.getDayOfWeek() == DayOfWeek.FRIDAY) {
return "It's Friday!"; // code branch is only taken on Fridays, cannot be tested on other days
}
Snippet of Compliant Code
final Instant instant = Instant.now(clock); // Compliant: clock dependency can be injected and controlled
// [...] decisions or serialization based on actual value of instant can be tested reliably by injecting a specific clock
final LocalDate today = LocalDate.now(clock); // Compliant: injected clock dependency
if (today.getDayOfWeek() == DayOfWeek.FRIDAY) {
return "It's Friday!"; // can be tested by injecting a clock that points to a Friday
}
External references and/or language specifications
- Instant (Java Platform SE 8 )
- LocalDate (Java Platform SE 8 )
- LocalDateTime (Java Platform SE 8 )
- MonthDay (Java Platform SE 8 )
- Year (Java Platform SE 8 )
- YearMonth (Java Platform SE 8 )
- Clock (Java Platform SE 8 )
Blog post explaining the issue and what should be done instead
Type
Code Smell
Tags
testability