Rendszeridő felülírása a Java teszteléséhez

1. Áttekintés

Ebben a gyors bemutatóban a következőkre fogunk összpontosítani a teszteléshez szükséges rendszeridő felülbírálásának különböző módjai.

Néha van egy logika az aktuális dátum körül a kódunkban. Talán néhány függvényhívás, mint pl új dátum () vagy Calendar.getInstance (), amelyek végül felhívni fogják System.CurrentTimeMillis.

Bevezetés a Java óra, kérjük, olvassa el ezt a cikket itt. Vagy az AspectJ használatára itt.

2. A Clock in használata java.time

A java.time csomagolás Java 8 tartalmaz egy absztrakt osztályt java.time.Clock azzal a céllal, hogy szükség esetén alternatív órákat csatlakoztathasson. Ezzel összekapcsolhatjuk saját megvalósításunkat, vagy megtalálhatunk egy olyan megoldást, amely már az igényeink kielégítésére készült.

Céljaink elérése érdekében a fenti könyvtár statikus módszereket tartalmaz speciális megvalósításokhoz. Közülük kettőt fogunk használni, ami megváltoztathatatlan, szálbiztos és sorosítható megvalósítást eredményez.

Az első az rögzített. Ebből, megszerezhetjük a Óra hogy mindig ugyanazt adja vissza Azonnali, annak biztosítása, hogy a tesztek ne függjenek az aktuális órától.

Használatához szükségünk van egy Azonnali és a ZoneOffset:

Instant.now (Clock.fixed (Instant.parse ("2018-08-22T10: 00: 00Z"), ZoneOffset.UTC))

A második statikus módszer az ellentételezés. Ebben az órában egy másik óra beburkolódik, amely a visszaküldött objektummá teszi a későbbi vagy korábbi pillanatok megszerzését a megadott időtartamra.

Más szavakkal, szimulálni lehet a futást a jövőben, a múltban vagy bármely tetszőleges időpontban:

Clock constantClock = Clock.fixed (ofEpochMilli (0), ZoneId.systemDefault ()); // tovább a jövőbe: Óraóra = Clock.offset (konstansClock, Duration.ofSeconds (10)); // visszatekerés negatív értékkel: clock = Clock.offset (constantClock, Duration.ofSeconds (-5)); // a 0 időtartam ugyanarra az órára tér vissza: clock = Clock.offset (constClock, Duration.ZERO);

A ... val Időtartam osztályban nanoszekundumoktól napokig lehet manipulálni. Ezenkívül tagadhatunk egy időtartamot, ami azt jelenti, hogy ilyen időtartamú másolatot kapunk a negatív hosszúsággal.

3. A képorientált programozás használata

A rendszeridő felülbírálásának másik módja az AOP. Ezzel a megközelítéssel képesek vagyunk szőni a Rendszer osztály előre megadott értéket ad vissza, amelyet a teszteseteinken belül beállíthatunk.

Ezenkívül lehetséges az alkalmazásosztályok szövése a hívás átirányításához System.currentTimeMillis () vagy a új dátum () egy másik saját közüzemi osztályba.

Ennek egyik módja az AspectJ használata:

nyilvános aspektus ChangeCallsToCurrentTimeInMillisMethod {long around (): call (public static native long java.lang.System.currentTimeMillis ()) && within (user.code.base.pckg. *) {return 0; }} 

A fenti példában minden hívást elkapunk System.currentTimeMillis() egy meghatározott csomagban, ami ebben az esetben az user.code.base.pckg. *, és nulla visszatérése minden alkalommal, amikor ez az esemény megtörténik.

Ezen a helyen nyilatkozhatunk saját megvalósításunkról, hogy ezredmásodpercek alatt elérjük a kívánt időt.

Az AspectJ használatának egyik előnye, hogy közvetlenül bytecode szinten működik, így a működéséhez nem kell az eredeti forráskód.

Ezért nem kellene újrafordítanunk.

4. A gúnyolódás Instant.now () Módszer

Használhatjuk a Azonnali osztály, hogy az idővonal pillanatnyi pontját képviselje. Normál esetben felhasználhatjuk eseményünk időbélyegeinek rögzítésére alkalmazásunkban. A Most() Ennek az osztálynak a módszere lehetővé teszi számunkra, hogy az aktuális pillanatot az UTC időzóna rendszerórájáról kapjuk meg.

Lássunk néhány alternatívát a viselkedésének megváltoztatásához, amikor tesztelünk.

4.1. Túlterhelés Most() Val,-vel Óra

Túlterhelhetjük a Most() módszer fix Óra példa. Az osztályok közül sok a java.time csomag van egy Most() módszer, amely a Óra paraméter, ami miatt ez a preferált megközelítés:

@Test public void givenFixedClock_whenNow_thenGetFixedInstant () {String instantExpected = "2014-12-22T10: 15: 30Z"; Óraóra = Óra.javítva (Instant.parse (instantExpected), ZoneId.of ("UTC")); Instant instant = Instant.now (óra); assertThat (instant.toString ()). isEqualTo (instantExpected); }

4.2. Használata PowerMock

Ezen felül, ha módosítanunk kell a Most() metódus paraméterek elküldése nélkül, használhatjuk PowerMock:

@RunWith (PowerMockRunner.class) @PrepareForTest ({Instant.class}) nyilvános osztály InstantUnitTest {@Test public void givenInstantMock_whenNow_thenGetFixedInstant () {String instantExpected = "2014-12-22T10: 15: 30Z"; Óraóra = Óra.javítva (Instant.parse (instantExpected), ZoneId.of ("UTC")); Instant instant = Instant.now (óra); mockStatic (Instant.class); mikor (Instant.now ()). thenReturn (azonnali); Instant now = Instant.now (); assertThat (now.toString ()). isEqualTo (instantExpected); }}

4.3. Használata JMockit

Alternatív megoldásként használhatjuk a JMockit könyvtár.

JMockit a statikus módszer gúnyolódásának két módját kínálja nekünk. Az egyik a Minta darab osztály:

@Test public void givenInstantWithJMock_whenNow_thenGetFixedInstant () {String instantExpected = "2014-12-21T10: 15: 30Z"; Óraóra = Óra.javítva (Instant.parse (instantExpected), ZoneId.of ("UTC")); új MockUp () {@Mock public Instant now () {return Instant.now (clock); }}; Instant now = Instant.now (); assertThat (now.toString ()). isEqualTo (instantExpected); }

A másik pedig a Elvárások osztály:

@Test public void givenInstantWithExpectations_whenNow_thenGetFixedInstant () {Clock clock = Clock.fixed (Instant.parse ("2014-12-23T10: 15: 30.00Z"), ZoneId.of ("UTC"); Instant instantExpected = Instant.now (óra); új elvárások (Instant.class) {{Instant.now (); eredmény = instantExpected; }}; Instant now = Instant.now (); assertThat (most) .isEqualTo (instantExpected); }

5. A gúnyolódás LocalDateTime.now () Módszer

Egy másik hasznos osztály a java.time csomag a LocalDateTime osztály. Ez az osztály az ISO-8601 naptárrendszerben időzóna nélküli dátumot és időt jelent. A Most() Ennek az osztálynak a módszere lehetővé teszi számunkra, hogy az alapértelmezett időzónában megkapjuk az aktuális dátum-időt a rendszer órájáról.

Ugyanazokat az alternatívákat használhatjuk gúnyra, mint korábban láttuk. Például a túlterhelés Most() fixel Óra:

@Test public void givenFixedClock_whenNow_thenGetFixedLocalDateTime () {Clock clock = Clock.fixed (Instant.parse ("2014-12-22T10: 15: 30.00Z"), ZoneId.of ("UTC"); String dateTimeExpected = "2014-12-22T10: 15: 30"; LocalDateTime dateTime = LocalDateTime.now (óra); assertThat (dateTime) .isEqualTo (dateTimeExpected); }

6. Következtetés

Ebben a cikkben különböző módszereket fedeztünk fel a rendszer tesztelési idejének felülbírálására. Először megnéztük a natív csomagot java.time és annak Óra osztály. Ezután láttuk, hogyan lehet alkalmazni egy szempontot a Rendszer osztály. Végül különböző alternatívákat tapasztaltunk a Most() módszer be Azonnali és LocalDateTime osztályok.

Mint mindig, a kódminták megtalálhatók a GitHubon.