В состав Java 8 вошёл пакет java.time, который на самом деле является ни чем иным, как старой и доброй библиотекой Joda-Time, в которой уже был специальный метод DateTimeUtils.setCurrentMillisFixed, с помощью которого можно было писать полноценные тесты. Я уже описывал это в одной из своих прошлых статей.
Однако в пакете java.time, работу с которым я уже тоже описывал в статье учебника, нет класса DateTimeUtils. Как же нам писать тесты?
В пакете java.time из Java 8 принят немного другой подход, основанный на классе Clock. Все методы, создающие экземпляры классов с текущей датой и / или временем принимают экземпляр этого класса в качестве параметра:
1 2 3 4 5 6 7 8 9 10 11 12 |
// Создаём Clock для текущей системной временной зоны // и текущей даты и времени. Clock clock = Clock.systemDefaultZone(); // Так как наш Clock создаёт экземпляры с текущим временем и/или датой // и с текущим временным поясом, то эти вызовы будут аналогичны // вызовам этих же самых фабричных методов без параметров. LocalDate localDate = LocalDate.now(clock); LocalTime localTime = LocalTime.now(clock); LocalDateTime localDateTime = LocalDateTime.now(clock); ZonedDateTime zonedDate = ZonedDateTime.now(clock); Instant instant = Instant.now(clock); |
В случае работы со Spring Framework лучше создать бин Clock:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
@Configuration public class DateTimeConfig { /** * Внедряйте зависимость на этот бин в те бины, где нужно получить * текущую дату и время. */ @Bean public Clock clock() { return Clock.systemUTC(); } } |
При написании тестов нам будет нужно просто создать экземпляр Clock, который всегда возвращает одну и ту же дату, одно и то же время, в одном и том же часовом поясе:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
Instant instant = LocalDateTime.of(2019, 8, 29, 15, 8, 0).toInstant(ZoneOffset.UTC); Clock clock = Clock.fixed(instant, ZoneId.of("UTC")); // Дальше можно спокойно вызывать тестируемые методы, которые создают // экземпляры LocalDate, LocalTime, Instant и т. д. с параметром clock, // который мы им дадим. Но нужно обязательно передавать этот clock, // который мы только что создали. ... // Эти вызовы всегда будут возвращать фиксированную дату и время // благодаря созданному нами Clock: LocalDate localDate = LocalDate.now(clock); LocalTime localTime = LocalTime.now(clock); LocalDateTime localDateTime = LocalDateTime.now(clock); ZonedDateTime zonedDate = ZonedDateTime.now(clock); Instant instant = Instant.now(clock); |
Вот и всё. Всем спасибо. Записал здесь только для того, чтобы не забыть.