Test integracyjny anulowania rezerwacji miejsca w kinie - problem z czasem i czytelnością

0

Napisałem test integracyjny, który sprawdza czy jeśli do seansu zostało mniej niż 24 godziny, to przy próbie anulowania rezerwacji miejsca poleci wyjątek, że jest za późno na to. Problem w tym, że wydaje mi się, że test wygląda zbyt skomplikowanie i jest mało czytelny. Wszystko przez problem z czasem. Najpierw muszę dodać seans, do którego zostało mniej niż 24 godziny i rezerwacje na niego, którą w teście będę próbował anulować, ale żeby to zrobić muszę się nakombinować z przekazywaniem Clocka.

@Test
void should_canceling_booking_be_impossible_when_less_than_24h_to_screening() throws Exception {
    //given
    var currentDate = getCurrentDate(clock);
    var hoursUntilBooking = 23;
    var sampleScreeningDate = currentDate.minusHours(hoursUntilBooking);
    var sampleScreening = addSampleScreening(filmFacade, screeningFacade, sampleScreeningDate);
    var sampleSeat = sampleScreening.seats().get(0);
    var timeDuringBooking = Clock.fixed(
            sampleScreeningDate.minusHours(hoursUntilBooking + 1).toInstant(ZoneOffset.UTC),
            ZoneOffset.UTC
    );
    var sampleSeatBooking = screeningFacade.bookSeat(
            sampleBookSeatDTO(
                    sampleScreening.id(),
                    sampleSeat.id()
            ),
            timeDuringBooking
    );

    //when
    var result = mockMvc.perform(
            patch("/seats-bookings/" + sampleSeatBooking.id() + "/cancel")
    );

    //then
    result
            .andExpect(status().isBadRequest())
            .andExpect(content().string(
                    "Too late for seat booking cancelling: " + sampleSeat.id()
            ));
}

Czy da się napisać ten test lepiej i bardziej czytelniej?

0

Jeżeli możesz użyć innej biblioteki/frameworku to spróbuj Spock. Tam Given, When, Then jest podstawa testu.

0

Zawsze mozesz sobie wyciagnac do funkcji metode ktora zwroci ci timestamp.

W Junit masz rozne providery inputu do testow: https://www.arhohuttunen.com/junit-5-parameterized-tests/ albo https://mkyong.com/junit5/junit-5-parameterized-tests/ i mozesz sobie np. @MethodSource uzyc.

3

Ja bym poszedł w stronę ukrycia szczegółów za jakimiś helperami albo wręcz stworzenie DSLa do testów integracyjnych. Wtedy twój test mógłby wyglądać mniej więcej tak (kod poglądowy, nie znam Javy, proszę nie bić):

@Test
    void should_canceling_booking_be_impossible_when_less_than_24h_to_screening() throws Exception {
        //given
        var now = DateTime.from(2023, 1, 1);
        var testCase = createTestCase().withScreening(
          createScreening()
            .withStartDate(now + DateTime.hours(23)) // to by można dalej ukryć, np. pod metodą `withImminentStartDate` - bo w sumie nas w teście nie interesuje, czy odwołać booking można do 24h przed, czy 1h przed, czy do tygodnia - chodzi o samo zachowanie
            .withSeatBooking(createSeatBooking().withBookingDate(now).build())
            .build()
         ).setup()
        

        //when
        var result = mockMvc.perform(
                patch("/seats-bookings/" + testCase.getSeatBookingId() + "/cancel")
        );

        //then
        result
                .andExpect(status().isBadRequest())
                .andExpect(content().string(
                        "Too late for seat booking cancelling: " + testCase.getSeatBookingId()
                ));
    }

Możesz nawet iść krok dalej i sekcje when i then też napisać w podobny sposób.
Setup dalej będzie skomplikowany, ale będzie ukryty za czytelnym kodem. Jeden rzut oka na taki test i widać co jest testowane.
Nie znam Javy więc wzorowałem się na https://github.com/Pharisaeus/almost-s3/blob/master/test/src/test/java/net/forprogrammers/almosts3/test/DownloadTest.java#L16 pewnie czytając ten kod więcej wyciągniesz niż z moich javopodobnych wypocin
Do tego polecam ten film i ten fragment filmu

1

Pseudo kod

@Test
void should_canceling_booking_be_impossible_when_less_than_24h_to_screening() throws Exception {
    //given
    setFixedTime("2022-01-01 12:30");
    sampleSeatBooking = bookForTime("2022-01-01 14:30");

    //when
    cancelBooking(sampleSeatBooking.id());

    //then
    expectCancelingFailed(sampleSeatBooking.id(), TOO_LATE_TO_CANCEL);
}

To mogłoby być w teście, wszystko inne może być ukryte w fixture'ach pod test.

0
Riddle napisał(a):

Pseudo kod

[...]

To mogłoby być w teście, wszystko inne może być ukryte w fixture'ach pod test.

Dobry kierunek, ale brakuje mi w tym teście informacji kiedy screening się zaczyna. To jest kluczowe w tym scenariuszu i wg mnie powinno być wyraźnie widoczne. Wynika to tylko z nazwy testu, która sama w sobie nic nie gwarantuje, a nawet kłóciłbym się, że jest do zmiany - jest zbyt specyficzna.

1 użytkowników online, w tym zalogowanych: 0, gości: 1