Рубрики
Без рубрики

Методы модульного тестирования, основанные на времени

Привет! Это мой первый пост из серии кратких советов по улучшению ваших тестов на Java, я надеюсь, что вы это сделаете… Помеченный как java, тестирование.

Привет! Это мой первый пост из серии кратких советов по улучшению ваших тестов на Java, я надеюсь, что сегодня вы чему-нибудь научитесь 👍

Вы когда-нибудь использовали Instant.now() , LocalDateTime.now() или ZonedDateTime.now() в вашем коде, только для того, чтобы потом было трудно протестировать?

Давайте возьмем пример:

public class Hohoho {

    public String isItChristmasYet() {
        LocalDate now = LocalDate.now();

        if (now.getMonth() == Month.DECEMBER) {
            if (now.getDayOfMonth() == 25) {
                return "Yes! Merry Christmas! 🎅";
            }
            else if (now.getDayOfMonth() == 24) {
                return "Almost there! 😁";
            }
        }
        return "Not yet 😔";
    }
}

Как бы вы протестировали этот метод?

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

Вы также можете использовать некоторые библиотеки, такие как Powermockito, чтобы имитировать статический метод LocalDate.now() но это также повлияло бы на другие тесты.

Вот совет: используйте java.time. Часы !

Каждый раз, когда вам нужно использовать метод *.now(), передавайте объект Clock в качестве параметра. Вы можете установить часы в качестве системных по умолчанию в своем конструкторе и добавить метод setter, чтобы переопределить его во время тестов.

Давайте применим это в нашем примере:

public class Hohoho {

    private Clock clock;

    public Hohoho() {
        // Set a normal value for the clock, here UTC
        this.clock = Clock.systemUTC();
    }

    // For testing purpose : override the clock
    public void setClock(Clock clock) {
        this.clock = clock;
    }

    public String isItChristmasYet() {
        LocalDate now = LocalDate.now(clock); // <- use the clock

        if (now.getMonth() == Month.DECEMBER) {
            if (now.getDayOfMonth() == 25) {
                return "Yes! Merry Christmas! 🎅";
            }
            else if (now.getDayOfMonth() == 24) {
                return "Almost there! 😁";
            }
        }
        return "Not yet 😔";
    }
}

Если вы хотите избежать установки, вы можете ввести часы с помощью внедрения зависимостей. Лично я не возражаю против того, чтобы в этом случае был сеттер.

Теперь давайте посмотрим, как это поможет нашим тестам:

class HohohoTest {

    private Hohoho underTest = new Hohoho();

    @DisplayName("Should respond 'Not Yet' in February")
    @Test
    void februaryTest() {
        // Fix the clock to my birthday
        Clock clock = Clock.fixed(Instant.parse("2022-02-21T12:00:00Z"), ZoneId.of("UTC"));
        underTest.setClock(clock);

        String actual = underTest.isItChristmasYet();

        assertThat(actual).isEqualTo("Not yet 😔");
    }

    @DisplayName("Should respond 'Almost there' the 24th of December")
    @Test
    void december24thTest() {
        // Fix the clock to christmas eve
        Clock clock = Clock.fixed(Instant.parse("2022-12-24T12:00:00Z"), ZoneId.of("UTC"));
        underTest.setClock(clock);

        String actual = underTest.isItChristmasYet();

        assertThat(actual).isEqualTo("Almost there! 😁");
    }

    @DisplayName("Should respond 'Yes' on Christmas")
    @Test
    void christmasTest() {
        // Fix the clock to christmas day
        Clock clock = Clock.fixed(Instant.parse("2022-12-25T12:00:00Z"), ZoneId.of("UTC"));
        underTest.setClock(clock);

        String actual = underTest.isItChristmasYet();

        assertThat(actual).isEqualTo("Yes! Merry Christmas! 🎅");
    }

}

Фиксируя объект Clock к определенному моменту времени, каждый метод now(), который использует часы, вернет точно такой же результат.

Это означает, что ваш тест всегда будет последовательным, используя одни и те же значения каждый раз, независимо от того, когда они выполняются: будь то в канун нового года, 28 февраля или при переходе с зимнего времени на летнее!

Есть ли у вас другой подход к тестированию методов, чувствительных ко времени? Дайте мне знать в комментариях! 👍

Оригинал: “https://dev.to/daviddasilva/unit-testing-time-driven-methods-n77”