Jak testować rzeczy oparte o czas

0

Załóżmy, że chce przetestować rzecz która do pewnego momentu można robić, a później już nie. Jako prosty przykład:
zakłady do meczy można tworzyć, edytować do momentu rozpoczęcia meczu.

Jak teraz w teście 'zasymulować' upływ czasu? Ze względu na pozostałe moje testy, mockowanie będzie bardzo niewygodne (stawiam cały system w pamięci na czas testu i na całym testuję)
Przekazywać do modułu jakiś zewnętrzny clock? (tworzy to kolejne zależności). Wtedy mógłbym już ręcznie podczas testu ustawiać godzinę 'świata'. Czy jest na to jakiś ładniejszy sposób?

2

Zawsze mam jakiś TimeService, który wystawia Clocka lub coś podobnego.
Zasada, że nikt nie robi po prostu w kodzie new Date() czy LocalDateTime.now() jak popadnie to podstawa.

0

W Javie 8 jest już java.time.Clock, więc nawet nie trzeba nowej klasy tworzyć. Clocka można użyć jako parametru do innych klas z java.time, np zamiast LocalDateTime.now() używamy LocalDateTime.now(clock).

0

@Wibowit: ale wydaje mi się że rozwiązanie z Clockiem jest nieco mniej czytelne, ja bym zastosował zwykły jakiś "TimeProvider"

0

@scibi92
@jarekr000000
@Wibowit

Łatwiej na potrzeby testów zrobić swojego TimeProvider niż czystego clocka chociażby przez to ze Clock jest słabo modyfikowalny przez co jego zmiana wymagałaby przekazania go po wszystkich klasach, a settery wszędzie nie są zbytnio ładną rzeczą chyba.

0

Clock jest klasą abstrakcyjną i możesz stworzyć własnego MutableClock na potrzeby testów.

0

Nie wiem w jaki sposób zrobienie Clocka niemutowalnego miałoby utrudnić testowanie, przeciez mógłbys to każdego testcase wrzucić nowa instancje Clocka. Chociaz ten clock jest po prostu jakims słabym pomysłem IMO

0

Tak po prawdzie clock to pikuś. W bardziej skomplikowanych systemach mamy batche, odpalane z jakiegoš schedulera, np co godzinę. Jakieś heart beaty, timeouty. Wtedy fajne jest jak mamy clock.fastfoward(1, Hour) i te wszystkie akcje się odpalają. Tylko raz widziałem system, w którym to jako tako było zrobione. ( i to nie był mój system :( )

0

Oto implementacja MutableClock w Scali:

class MutableClock(var clock: Clock = Clock.systemUTC()) extends Clock { // tutaj w sumie jeszcze słówko volatile by się przydało
  override def getZone = clock.getZone
  override def instant = clock.instant
}

Użycie:

val clock = new MutableClock()
val time1 = LocalDateTime.now(clock)
clock.clock = Clock.offset(clock.clock, Duration.ofHours(1)) // przyspieszamy czas o godzinę
val time2 = LocalDateTime.now(clock)
0

java.time.instant ?

Instant daysAgo = Instant.now().minus(25, ChronoUnit.HOURS);

1

Tobie raczej nie do końca przyda się to rozwiazanie, ale może innym: w RxJavie mamy fajny Scheduler, na którym możemy robić coś o czym jarek pisal wyżej tj. scheduler.advanceTimeBy(1, TimeUnit.SECONDS), więcej info np. tutaj, punkt 9.

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