Nadjačavanje sistemskog vremena za testiranje na Javi

1. Pregled

U ovom brzom vodiču usredotočit ćemo se na različiti načini nadjačavanja vremena sustava za testiranje.

Ponekad u našem kodu postoji logika oko trenutnog datuma. Možda neki pozivi funkcija poput novi datum () ili Calendar.getInstance (), koje će na kraju nazvati System.CurrentTimeMillis.

Za uvod u upotrebu Java sat, pogledajte ovaj članak ovdje. Ili, za uporabu AspectJ, ovdje.

2. Korištenje sata u java.vrijeme

The java.vrijeme paket u Java 8 uključuje apstraktnu nastavu java.time.Clock sa svrhom da omoguće priključivanje zamjenskih satova prema potrebi. Uz to možemo priključiti vlastitu implementaciju ili pronaći onu koja je već napravljena da zadovolji naše potrebe.

Da bismo postigli svoje ciljeve, gornja knjižnica uključuje statičke metode koje daju posebne implementacije. Koristit ćemo dva od njih koji vraćaju nepromjenjivu implementaciju, sigurnu za nit i serializirajuću.

Prva je fiksne. Iz toga, možemo dobiti a Sat to uvijek vraća isto Trenutak, osiguravajući da testovi ne ovise o trenutnom satu.

Da bismo ga koristili, potreban nam je Trenutak i a ZoneOffset:

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

Druga statička metoda je ofset. U ovaj sat umota drugi sat što ga čini vraćenim objektom sposobnim za dobivanje trenutaka koji su kasnije ili ranije za određeno trajanje.

Drugim riječima, moguće je simulirati trčanje u budućnosti, u prošlosti ili u bilo kojem proizvoljnom trenutku:

Clock constantClock = Clock.fixed (ofEpochMilli (0), ZoneId.systemDefault ()); // idemo u budućnost: Clock clock = Clock.offset (constantClock, Duration.ofSeconds (10)); // premotavanje natrag s negativnom vrijednošću: clock = Clock.offset (constantClock, Duration.ofSeconds (-5)); // trajanje 0 vraća se na isti sat: clock = Clock.offset (constClock, Duration.ZERO);

Uz Trajanje klase, moguće je manipulirati od nanosekundi do dana. Također, možemo negirati trajanje, što znači dobiti kopiju tog trajanja s negativnom duljinom.

3. Korištenje programiranja usmjerenog na aspekt

Drugi način za nadjačavanje sistemskog vremena je AOP. Ovim pristupom, mi smo u mogućnosti tkati Sustav klasa za vraćanje unaprijed definirane vrijednosti koju možemo postaviti u okviru naših test slučajeva.

Također je moguće povezati klase aplikacija za preusmjeravanje poziva na System.currentTimeMillis () Ili do novi datum () u drugu vlastitu klasu korisnosti.

Jedan od načina da se to primijeni je upotreba AspectJ:

javni aspekt ChangeCallsToCurrentTimeInMillisMethod {long around (): poziv (javni statični izvorni long java.lang.System.currentTimeMillis ()) && unutar (user.code.base.pckg. *) {return 0; }} 

U gornjem primjeru, hvatamo svaki poziv System.currentTimeMillis() unutar određenog paketa, što je u ovom slučaju user.code.base.pckg. *, i vraćanje nule svaki put kad se dogodi ovaj događaj.

Na ovom mjestu možemo izjaviti vlastitu implementaciju kako bismo u milisekundama dobili željeno vrijeme.

Jedna od prednosti korištenja AspectJ-a je ta što radi izravno na razini bajt-koda, tako da mu izvorni izvorni kod ne treba.

Iz tog razloga ne bismo ga trebali ponovno sastaviti.

4. Ruganje Instant.now () Metoda

Možemo koristiti Trenutak klasa koja predstavlja trenutnu točku na vremenskoj traci. Obično ga možemo koristiti za bilježenje vremenskih žigova događaja u našoj aplikaciji. The sada() metoda ove klase omogućuje nam dobivanje trenutnog trenutka sa sistemskog sata u UTC vremenskoj zoni.

Pogledajmo neke alternative za promjenu njegovog ponašanja kada testiramo.

4.1. Preopterećenje sada() S Sat

Možemo preopteretiti sada() metoda s fiksnom Sat primjer. Mnogi razredi u java.vrijeme paket imaju a sada() metoda koja traje a Sat parametar, što čini ovaj naš preferirani pristup:

@Test javna praznina danaFixedClock_whenNow_thenGetFixedInstant () {String instantExpected = "2014-12-22T10: 15: 30Z"; Sat sata = Clock.fixed (Instant.parse (instantExpected), ZoneId.of ("UTC")); Instant instant = Instant.now (sat); assertThat (instant.toString ()). isEqualTo (instantExpected); }

4.2. Koristeći PowerMock

Osim toga, ako trebamo izmijeniti ponašanje sada() metodu bez slanja parametara, možemo koristiti PowerMock:

@RunWith (PowerMockRunner.class) @PrepareForTest ({Instant.class}) javna klasa InstantUnitTest {@Test javna praznina givenInstantMock_whenNow_thenGetFixedInstant () {String instantExpected = "2014-12-22T10: 15: 30Z"; Sat sata = Clock.fixed (Instant.parse (instantExpected), ZoneId.of ("UTC")); Instant instant = Instant.now (sat); mockStatic (Instant.class); when (Instant.now ()). thenReturn (instant); Trenutno odmah = Instant.now (); assertThat (now.toString ()). isEqualTo (instantExpected); }}

4.3. Koristeći JMockit

Alternativno, možemo koristiti JMockit knjižnica.

JMockit nudi nam dva načina ismijavanja statičke metode. Jedan koristi Maketa razred:

@Test javna praznina givenInstantWithJMock_whenNow_thenGetFixedInstant () {String instantExpected = "2014-12-21T10: 15: 30Z"; Sat sata = Clock.fixed (Instant.parse (instantExpected), ZoneId.of ("UTC")); novi MockUp () {@Mock javni Instant odmah () {return Instant.now (sat); }}; Trenutno odmah = Instant.now (); assertThat (now.toString ()). isEqualTo (instantExpected); }

A drugi koristi Očekivanja razred:

@Test javna praznina givenInstantWithExpecations_whenNow_thenGetFixedInstant () {Clock clock = Clock.fixed (Instant.parse ("2014-12-23T10: 15: 30.00Z"), ZoneId.of ("UTC")); Instant instantExpected = Instant.now (sat); nova očekivanja (Instant.class) {{Instant.now (); rezultat = instantOčekivano; }}; Trenutno odmah = Instant.now (); assertThat (sada) .isEqualTo (instantExpected); }

5. Ruganje LocalDateTime.now () Metoda

Još jedna korisna klasa u java.vrijeme paket je LocalDateTime razred. Ova klasa predstavlja datum i vrijeme bez vremenske zone u kalendarskom sustavu ISO-8601. The sada() metoda ove klase omogućuje nam dobivanje trenutnog datuma i vremena sa sistemskog sata u zadanoj vremenskoj zoni.

Možemo se koristiti istim alternativama kako bismo se tome rugali kao što smo vidjeli prije. Na primjer, preopterećenje sada() s fiksnim Sat:

@Test javna praznina danaFixedClock_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 (sat); assertThat (dateTime) .isEqualTo (dateTimeExpected); }

6. Zaključak

U ovom smo članku istražili različite načine nadjačavanja sistemskog vremena za testiranje. Prvo smo pogledali izvorni paket java.vrijeme I je Sat razred. Zatim smo vidjeli kako primijeniti aspekt za tkanje Sustav razred. Napokon, vidjeli smo različite alternative ismijavanju sada() metoda na Trenutak i LocalDateTime razreda.

Kao i uvijek, uzorci koda mogu se naći na GitHubu.

$config[zx-auto] not found$config[zx-overlay] not found