Programovanie

Výukový program JUnit 5, časť 1: Testovanie jednotiek s JUnit 5, Mockito a Hamcrest

JUnit 5 je nový de facto štandard pre vývoj jednotkových testov v Jave. Táto najnovšia verzia zanechala obmedzenia v prostredí Java 5 a integrovala mnoho funkcií z prostredia Java 8, najmä podporu výrazov lambda.

V tejto prvej polovici dvojdielneho úvodu do JUnit 5 začnete s testovaním v JUnit 5. Ukážem vám, ako nakonfigurovať projekt Maven na používanie JUnit 5, ako písať testy pomocou @Test a @ParameterizedTest anotácie a ako pracovať s novými anotáciami životného cyklu v JUnit 5. Uvidíte tiež krátky príklad použitia filtračných značiek a ukážem vám, ako integrovať JUnit 5 s knižnicou tvrdení tretích strán - v tomto prípade , Hamcrest. Na záver získate rýchly výukový úvod do integrácie JUnit 5 s programom Mockito, aby ste mohli písať robustnejšie jednotkové testy pre zložité systémy v reálnom svete.

stiahnuť Získajte kód Získajte zdrojový kód pre príklady v tejto príručke. Vytvoril Steven Haines pre JavaWorld.

Vývoj riadený testami

Ak vyvíjate kód Java nejaký čas, pravdepodobne dôverne poznáte vývoj založený na testoch, preto túto časť stručne uvediem. Je dôležité to pochopiť prečo píšeme však jednotkové testy, ako aj stratégie, ktoré vývojári používajú pri navrhovaní jednotkových testov.

Test-driven development (TDD) je proces vývoja softvéru, ktorý prelína kódovanie, testovanie a dizajn. Jedná sa o testovací prístup, ktorého cieľom je zlepšiť kvalitu vašich aplikácií. Vývoj založený na testoch je definovaný týmto životným cyklom:

  1. Pridajte test.
  2. Spustite všetky svoje testy a sledujte, ako nový test zlyháva.
  3. Implementujte kód.
  4. Spustite všetky svoje testy a sledujte úspešnosť nového testu.
  5. Refaktorujte kód.

Obrázok 1 zobrazuje tento životný cyklus TDD.

Steven Haines

Písanie testov pred napísaním kódu má dvojaký účel. Najprv vás to prinúti zamyslieť sa nad obchodným problémom, ktorý sa snažíte vyriešiť. Ako by sa napríklad mali správať úspešné scenáre? Aké podmienky by mali zlyhať? Ako by mali zlyhať? Po druhé, prvé testovanie vám dá väčšiu dôveru vo vaše testy. Kedykoľvek po napísaní kódu napíšem testy, vždy ich musím rozbiť, aby som sa ubezpečil, že skutočne zachytávajú chyby. Písanie testov sa najskôr vyhne tomuto ďalšiemu kroku.

Písanie testov na šťastnú cestu je zvyčajne jednoduché: Ak zadáte dobrý vstup, mala by trieda vrátiť deterministickú odpoveď. Ale písanie negatívnych (alebo zlyhaných) testovacích prípadov, najmä pre zložité komponenty, môže byť komplikovanejšie.

Ako príklad zvážte napísanie testov pre databázové úložisko. Na šťastnú cestu vložíme záznam do databázy a dostaneme späť vytvorený objekt vrátane všetkých vygenerovaných kľúčov. V skutočnosti musíme brať do úvahy aj možnosť konfliktu, napríklad vloženie záznamu s jedinečnou hodnotou stĺpca, ktorý už drží iný záznam. Čo sa ďalej stane, keď sa úložisko nemôže pripojiť k databáze, možno preto, že sa zmenilo používateľské meno alebo heslo? Čo sa stane, ak sa pri prenose vyskytne chyba v sieti? Čo sa stane, ak sa žiadosť nedokončí v rámci vami určeného časového limitu?

Ak chcete vytvoriť robustný komponent, musíte zvážiť všetky pravdepodobné a nepravdepodobné scenáre, vyvinúť pre ne testy a napísať svoj kód tak, aby vyhovoval týmto testom. Ďalej v článku sa pozrieme na stratégie vytvárania rôznych scenárov zlyhaní spolu s niektorými novými funkciami v JUnit 5, ktoré vám môžu pomôcť tieto scenáre otestovať.

Prijatie JUnit 5

Ak JUnit používate už nejaký čas, niektoré zmeny v JUnit 5 budú úpravou. Tu je zhrnutie na vysokej úrovni, ktoré sa líši medzi týmito dvoma verziami:

  • JUnit 5 je teraz zabalený v org.junit.jupiter skupina, ktorá zmení spôsob, akým to zahrniete do svojich projektov Maven a Gradle.
  • JUnit 4 vyžadoval minimálne JDK 5 JDK; JUnit 5 vyžaduje minimálne 8 JDK.
  • JUnit 4 @ Predtým, @BeforeClass, @ Potoma @Po hodine anotácie boli nahradené @ Predtým každý, @BeforeAll, @AfterEacha @Po všetkom, resp.
  • JUnit 4 @Ignorovať anotácia bola nahradená @Zakázané anotácia.
  • The @Category anotácia bola nahradená @Tag anotácia.
  • JUnit 5 pridáva novú sadu metód tvrdenia.
  • Bežce boli nahradené rozšíreniami s novým API pre implementátorov rozšírení.
  • JUnit 5 zavádza predpoklady, ktoré zastavujú vykonávanie testu.
  • JUnit 5 podporuje vnorené a dynamické testovacie triedy.

Väčšinu týchto nových funkcií preskúmame v tomto článku.

Testovanie jednotiek pomocou JUnit 5

Začnime jednoduchým príkladom komplexného príkladu konfigurácie projektu na použitie JUnit 5 pre testovanie jednotky. Zoznam 1 zobrazuje a MathTools trieda, ktorej metóda prevádza čitateľa a menovateľa na a dvojitý.

Zoznam 1. Príklad projektu JUnit 5 (MathTools.java)

 balíček com.javaworld.geekcap.math; public class MathTools {public static double convertToDecimal (int čitatel, int denominator) {if (denominator == 0) {throw new IllegalArgumentException ("Denominator must not be 0"); } návrat (dvojitý) čitateľ / (dvojitý) menovateľ; }}

Máme dva primárne scenáre testovania MathTools trieda a jej metóda:

  • A platný test, v ktorom pre čitateľa a menovateľa odovzdáme nenulové celé čísla.
  • A scenár zlyhania, v ktorom odovzdáme nulovú hodnotu pre menovateľa.

Výpis 2 zobrazuje testovaciu triedu JUnit 5 na testovanie týchto dvoch scenárov.

Zoznam 2. Testovacia trieda JUnit 5 (MathToolsTest.java)

 balíček com.javaworld.geekcap.math; import java.lang.IllegalArgumentException; importovať org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; trieda MathToolsTest {@Test void testConvertToDecimalSuccess () {dvojitý výsledok = MathTools.convertToDecimal (3, 4); Assertions.assertEquals (0,75, výsledok); } @Test void testConvertToDecimalInvalidDenominator () {Assertions.assertThrows (IllegalArgumentException.class, () -> MathTools.convertToDecimal (3, 0)); }}

V zozname 2 je testConvertToDecimalInvalidDenominator metóda vykonáva MathTools :: convertToDecimal metóda vo vnútri tvrdiťHodí hovor. Prvý argument je očakávaný typ výnimky, ktorá sa má vyvolať. Druhým argumentom je funkcia, ktorá vyvolá túto výnimku. The tvrdiťHodí metóda vykoná funkciu a overí, či je vyvolaný očakávaný typ výnimky.

Trieda Assertions a jej metódy

Theorg.junit.jupiter.api.Test anotácia označuje skúšobnú metódu. Všimnite si, že @Test anotácia teraz pochádza z balíka JUnit 5 Jupiter API namiesto z JUnit 4 org.junit balíček. The testConvertToDecimalSuccess metóda najskôr vykoná MathTools :: convertToDecimal metóda s čitateľom 3 a menovateľom 4, potom tvrdí, že výsledok sa rovná 0,75. The org.junit.jupiter.api. Tvrdenia trieda poskytuje súbor statický metódy na porovnanie skutočných a očakávaných výsledkov. The Tvrdenia trieda má nasledujúce metódy, ktoré pokrývajú väčšinu primitívnych dátových typov:

  • assertArrayEquals porovnáva obsah skutočného poľa s očakávaným poľom.
  • assertEquals porovnáva skutočnú hodnotu s očakávanou.
  • assertNotEquals porovnáva dve hodnoty, aby overil, že nie sú rovnaké.
  • tvrdiť Pravda potvrdzuje, že zadaná hodnota je pravdivá.
  • tvrdiťFaloš potvrdzuje, že zadaná hodnota je nepravdivá.
  • assertLinesMatch porovnáva dva zoznamy Strings.
  • assertNull potvrdzuje, že zadaná hodnota je nulová.
  • assertNotNull potvrdzuje, že zadaná hodnota nie je nulová.
  • tvrdiťSame overuje, že dve hodnoty odkazujú na ten istý objekt.
  • assertNotSame overuje, že dve hodnoty neodkazujú na ten istý objekt.
  • tvrdiťHodí overuje, že vykonanie metódy vyvolá očakávanú výnimku (môžete ju vidieť v testConvertToDecimalInvalidDenominator príklad vyššie).
  • assertTimeout overuje, či sa dodaná funkcia dokončí v stanovenom časovom limite.
  • assertTimeoutPreventívne overuje, či sa dodaná funkcia dokončí v rámci zadaného časového limitu, ale akonáhle sa časový limit dosiahne, zabije sa vykonanie funkcie.

Ak niektorá z týchto metód tvrdenia zlyhá, test jednotky sa označí ako neúspešný. Toto oznámenie o zlyhaní sa po vykonaní testu zapíše na obrazovku a potom sa uloží do súboru správy.

Použitie delty s assertEquals

Pri použití plavák a dvojitý hodnoty v assertEquals, môžete tiež určiť a delta to predstavuje prahovú hodnotu rozdielu medzi týmito dvoma. V našom príklade sme mohli pridať deltu 0,001, ak by sa 0,75 skutočne vrátila ako 0,750001.

Analýza výsledkov vášho testu

Okrem overenia hodnoty alebo správania sa tvrdiť metódy môžu prijať aj textový popis chyby, ktorý vám pomôže diagnostikovať zlyhania. Napríklad:

 Assertions.assertEquals (0,75, výsledok, „Hodnota MathTools :: convertToDecimal nevrátila správnu hodnotu 0,75 pre 3/4"); Assertions.assertEquals (0,75, result, () -> "Hodnota MathTools :: convertToDecimal nevrátila správnu hodnotu 0,75 pre 3/4"); 

Na výstupe sa zobrazí očakávaná hodnota 0,75 a skutočná hodnota. Taktiež zobrazí zadanú správu, ktorá vám pomôže pochopiť kontext chyby. Rozdiel medzi týmito dvoma variáciami spočíva v tom, že prvá vždy vytvorí správu, aj keď sa nezobrazí, zatiaľ čo druhá vytvorí správu iba v prípade, že tvrdenie zlyhá. V takom prípade je konštrukcia správy triviálna, takže to nemá význam. Napriek tomu nie je potrebné zostaviť chybové hlásenie pre test, ktorý prejde, takže je zvyčajne najlepším postupom použiť druhý štýl.

Nakoniec, ak na vykonávanie svojich testov používate IDE ako IntelliJ, každá testovacia metóda sa zobrazí podľa názvu metódy. To je v poriadku, ak sú názvy metód čitateľné, ale môžete tiež pridať a @Zobraziť meno anotácia k vašim testovacím metódam na lepšiu identifikáciu testov:

@Test @DisplayName ("Test úspešnej desatinnej konverzie") void testConvertToDecimalSuccess () {double result = MathTools.convertToDecimal (3, 4); Assertions.assertEquals (0,751, výsledok); }

Prebieha testovanie jednotky

Ak chcete spustiť testy JUnit 5 z projektu Maven, musíte zahrnúť súbor maven-surefire-plugin v Maven pom.xml súbor a pridať novú závislosť. Zoznam 3 zobrazuje pom.xml súbor pre tento projekt.

Zoznam 3. Maven pom.xml pre príklad projektu JUnit 5

  4.0.0 com.javaworld.geekcap junit5 jar 1.0-SNAPSHOT org.apache.maven.plugins maven-compiler-plugin 3.8.1 8 8 org.apache.maven.plugins maven-surefire-plugin 3.0.0-M4 junit5 // maven.apache.org org.junit.jupiter test junit-jupiter 5.6.0 

JUnit 5 závislostí

JUnit 5 balí svoje komponenty do org.junit.jupiter skupinu a musíme pridať junit-jupiter artefakt, čo je artefakt agregátora, ktorý importuje nasledujúce závislosti:

  • junit-jupiter-api definuje API pre písanie testov a rozšírení.
  • junit-jupiter-motor je implementácia testovacieho motora, ktorá spúšťa jednotkové testy.
  • junit-jupiter-params poskytuje podporu pre parametrizované testy.

Ďalej musíme pridať maven-surefire-plugin na vykonanie testov zostavte doplnok.

Na záver nezabudnite zahrnúť maven-compiler-plugin s verziou Java 8 alebo novšou, takže budete môcť používať funkcie Java 8, ako napríklad lambdas.

Spustite ho!

Na spustenie testovacej triedy z vášho IDE alebo z Mavenu použite nasledujúci príkaz:

mvn čistý test

Ak ste úspešní, mali by ste vidieť výstup podobný tomuto:

 [INFO] ----------------------------------------------- -------- [INFO] TESTY [INFO] ----------------------------------- -------------------- [INFO] Beží com.javaworld.geekcap.math.MathToolsTest [INFO] Spustené testy: 2, Zlyhania: 0, Chyby: 0, Vynechané : 0, Uplynutý čas: 0,04 s - v com.javaworld.geekcap.math.MathToolsTest [INFO] [INFO] Výsledky: [INFO] [INFO] Spustené testy: 2, Zlyhania: 0, Chyby: 0, Vynechané: 0 [ INFO] [INFO] --------------------------------------------- --------------------------- [INFO] STAVEBNÝ ÚSPECH [INFO] --------------- -------------------------------------------------- ------- [INFO] Celkový čas: 3,832 s [INFO] Dokončené o: 2020-02-16T08: 21: 15-05: 00 [INFO] ------------- -------------------------------------------------- --------- 
$config[zx-auto] not found$config[zx-overlay] not found