Написание и тестирование удобных методов с использованием классов даты / времени Java 8 - PullRequest
0 голосов
/ 23 октября 2018

У меня есть несколько старых вспомогательных методов, написанных с использованием календарей, которые я хочу обновить, чтобы использовать классы Java.time. *, Представленные в Java 8. Некоторые из методов в моем классе получают такие значения, как текущее время или даже простотекущий час

Я планирую написать два варианта каждого метода: один, который предполагает, что часовой пояс является значением по умолчанию, определенным на этом компьютере, и один, который позволяет пользователю указать желаемый часовой пояс.

Я пытаюсь понять две основные вещи:

  1. Как получить текущую метку времени в моих методах.
  2. Как выполнить модульное тестирование моих результатов с помощью другой источник текущей отметки времени.

Что касается самих методов, я склонен создать ZonedDateTime следующим образом:

LocalDateTime currentDateTime = LocalDateTime.now();
ZoneId timeZoneDefault = ZoneId.systemDefault(); 
ZonedDateTime currentZonedDateTimeDefault = ZonedDateTime.of(currentDateTime, timeZoneDefault);

Затем я использовал бы DateTimeFormatter для получения части результата, котораяЯ действительно заботился о.Например, если бы я хотел текущий час от 24-часовых часов, а затем от 12-часовых часов, я сделал бы это:

DateTimeFormatter fmt = DateTimeFormatter.ofPattern("kk");
System.out.println("currentHour (24 hour clock): " + currentZonedDateTimeDefault.format(fmt));
DateTimeFormatter fmt2 = DateTimeFormatter.ofPattern("hh a");
System.out.println("currentHour (12 hour clock): " + currentZonedDateTimeDefault.format(fmt2));

Это нормально, или я должен использовать другой подход,возможно используя Instant?

Моя главная проблема - найти другой способ получить текущее время для моих модульных тестов, чтобы я мог сравнить ожидаемые результаты с реальными результатами.Я читал о Clocks и Instants и так далее, и чем больше я читаю, тем больше я запутываюсь.Некоторые подходы, похоже, получают текущее время из одного и того же источника, поэтому они предположительно покажут, что ожидаемый результат ВСЕГДА совпадает с фактическим результатом - но тогда ОБА может быть ошибочной в том же духе.

Может ли кто-нибудь подсказать мне наилучший способ вычисления текущего времени в заданном часовом поясе, который получает время отличным от способом, чем тот, который я использую в моем методе?

ОБНОВЛЕНИЕ: я работаю над своими удобными методами и использую это в каждом методе, который начинается с получения текущей даты и времени:

    LocalDateTime now = LocalDateTime.now();
    ZonedDateTime nowLocalTimeZone = ZonedDateTime.of(now, ZoneId.systemDefault());

Затем я получаю частьдата / время, которое я на самом деле хочу с кодом, подобным этому:

try {
        DateTimeFormatter format = DateTimeFormatter.ofPattern(MONTH_NUMBER_FORMAT);
        return Integer.parseInt(nowLocalTimeZone.format(format));
    }
    catch (DateTimeParseException excp) {
        throw excp;         
    }

Обратите внимание, что в методах все основано на LocalDateTime.now () без указания часов.

В моеммодульные тесты, я получил это как переменную класса:

    private Clock localClock = Clock.fixed(Instant.now(), ZoneId.systemDefault());

В типичном модульном тесте у меня есть такой код:

@Test
@DisplayName ("getCurrentMonthNumberLocal()")
void testGetCurrentMonthNumberLocal() {

    LocalDateTime now = LocalDateTime.now(localClock);
    ZonedDateTime nowLocalTimeZone = ZonedDateTime.of(now, ZoneId.systemDefault());

    //Normal cases
    assertEquals(nowLocalTimeZone.getMonthValue(), CurrentDateTimeUtils.getCurrentMonthNumberLocal());
}

Обратите внимание, что этот подход предполагает использованиеисправлены часы с именем localClock в качестве источника ожидаемого результата.

Когда я запускаю тесты, ожидаемые результаты соответствуют фактическому результату (по крайней мере, для тех немногих классов, которые я выполнил до сих пор, которые ищут номер года и месяца).

Делает ли этоПодход Убедитесь, что я получаю текущее время из двух разных источников, чтобы сравнение было действительным?Или я эффективно получаю ту же информацию из того же источника, например, системные часы на моем компьютере?

Я очень хочу, чтобы дата / время, которое я получаю от методов, пришли из другого источника, нежели дата / время, использованное для определения ожидаемых результатов в моих модульных тестах, чтобы я был уверен, что это действительный тестиначе я не вижу особого смысла в тестировании этих методов.(Полагаю, я мог бы просто отобразить результаты каждой функции и посмотреть, выглядит ли она примерно правильно. Довольно легко определить, верны ли год, месяц и день, если, возможно, вы не очень близки к концу того года, месяца илидень, в этом случае вы можете видеть значения для другого часового пояса и не знать его.)

1 Ответ

0 голосов
/ 24 октября 2018

В вашем тесте (и только во время теста!) Установите часы, используемые вашим классом удобства, чтобы вы могли прогнозировать желаемые / ожидаемые результаты независимо от часов компьютера:

public class ConvenienceTest {

    @Test
    public void testGetLocalHour() {
        Convenience underTest = new Convenience();

        ZoneId zone = ZoneId.of("America/Los_Angeles");

        ZonedDateTime fixedZdt = ZonedDateTime.now(zone).withHour(0);
        underTest.setClock(Clock.fixed(fixedZdt.toInstant(), zone));
        assertEquals("24", underTest.getLocalHour24HourClock());

        fixedZdt = fixedZdt.withHour(1);
        underTest.setClock(Clock.fixed(fixedZdt.toInstant(), zone));
        assertEquals("01", underTest.getLocalHour24HourClock());

        fixedZdt = fixedZdt.withHour(23);
        underTest.setClock(Clock.fixed(fixedZdt.toInstant(), zone));
        assertEquals("23", underTest.getLocalHour24HourClock());

        // TODO test with other time zones
    }

}

Чтобы это работалоэто, конечно, требует, чтобы ваш удобный класс мог принять Clock и использовать его:

public class Convenience {

    private Clock clock = Clock.systemDefaultZone();

    /** For testing only. Sets the clock from which to get the time. */
    void setClock(Clock clockForTest) {
        this.clock  = clockForTest;
    }

    public String getLocalHour24HourClock() {
        DateTimeFormatter fmt = DateTimeFormatter.ofPattern("kk");
        ZonedDateTime zdt = ZonedDateTime.now(clock);
        return zdt.format(fmt);
    }

}

В этой реализации тесты только что прошли на моем компьютере.

Шаг назад: есливаши удобные методы - это всего лишь тонкий слой поверх java.time, вы можете начать задумываться о том, какую ценность имеет модульный тест.Если он выполняет какую-то реальную работу (например, форматирование в приведенном выше примере, что-то, что регулярно идет не так), тест полезен, но если метод просто возвращает значение из одного вызова в java.time, вам может не понадобиться тест,Вы не должны тестировать java.time, желательно только свой собственный код.

...