Programování

Výukový program JUnit 5, část 1: Testování jednotek pomocí JUnit 5, Mockito a Hamcrest

JUnit 5 je nový de facto standard pro vývoj testů jednotek v Javě. Tato nejnovější verze zanechala omezení v prostředí Java 5 a integrovala mnoho funkcí z prostředí Java 8, zejména podporu výrazů lambda.

V této první polovině dvoudílného úvodu do JUnit 5 začnete s testováním pomocí JUnit 5. Ukážu vám, jak nakonfigurovat projekt Maven tak, aby používal JUnit 5, jak psát testy pomocí @Test a @ParameterizedTest anotace a jak pracovat s novými anotacemi životního cyklu v JUnit 5. Uvidíte také krátký příklad použití značek filtrů a ukážu vám, jak integrovat JUnit 5 s knihovnou tvrzení třetích stran - v tomto případě , Hamcrest. Nakonec získáte rychlý výukový úvod k integraci JUnit 5 s Mockito, abyste mohli psát robustnější testy jednotek pro složité systémy v reálném světě.

stáhnout Získat kód Získejte zdrojový kód pro příklady v tomto kurzu. Vytvořil Steven Haines pro JavaWorld.

Testovaný vývoj

Pokud jste vyvíjeli kód Java pro jakékoli časové období, jste pravděpodobně důvěrně obeznámeni s vývojem řízeným testem, takže tuto část stručně uvedu. Je důležité to pochopit proč píšeme jednotkové testy, ale také strategie, které vývojáři používají při navrhování jednotkových testů.

Test-driven development (TDD) je proces vývoje softwaru, který prolíná kódování, testování a design. Jedná se o testovací přístup, jehož cílem je zlepšit kvalitu vašich aplikací. Vývoj zaměřený na testování je definován následujícím životním cyklem:

  1. Přidejte test.
  2. Spusťte všechny své testy a sledujte, jak nový test selhává.
  3. Implementujte kód.
  4. Spusťte všechny své testy a sledujte, jak nový test uspěl.
  5. Refaktorujte kód.

Obrázek 1 ukazuje tento životní cyklus TDD.

Steven Haines

Psaní testů před psaním kódu má dvojí účel. Nejprve vás to donutí přemýšlet o obchodním problému, který se snažíte vyřešit. Například, jak by se měly chovat úspěšné scénáře? Jaké podmínky by měly selhat? Jak by měli selhat? Zadruhé, testování vám nejprve dá větší důvěru ve vaše testy. Kdykoli píšu testy po napsání kódu, vždy je musím rozbít, abych se ujistil, že skutečně chytají chyby. Psaní testů se nejprve vyhne tomuto dalšímu kroku.

Psaní testů pro šťastnou cestu je obvykle snadné: S dobrým vstupem by třída měla vrátit deterministickou odpověď. Ale psaní negativních (nebo neúspěšných) testovacích případů, zejména pro složité komponenty, může být komplikovanější.

Jako příklad zvažte psaní testů pro úložiště databáze. Na šťastné cestě vložíme záznam do databáze a přijmeme zpět vytvořený objekt, včetně všech vygenerovaných klíčů. Ve skutečnosti musíme také zvážit možnost konfliktu, jako je vložení záznamu s jedinečnou hodnotou sloupce, která je již držena jiným záznamem. Co se dále stane, když se úložiště nemůže připojit k databázi, snad proto, že se změnilo uživatelské jméno nebo heslo? Co se stane, když dojde k chybě sítě při přenosu? Co se stane, když se požadavek nedokončí ve stanoveném limitu časového limitu?

Chcete-li vytvořit robustní komponentu, musíte zvážit všechny pravděpodobné a nepravděpodobné scénáře, vyvinout pro ně testy a napsat svůj kód tak, aby vyhovoval těmto testům. Později v článku se podíváme na strategie pro vytváření různých scénářů selhání spolu s některými novými funkcemi v JUnit 5, které vám mohou tyto scénáře pomoci otestovat.

Přijetí JUnit 5

Pokud JUnit používáte nějakou dobu, některé změny v JUnit 5 budou úpravou. Zde je souhrn na vysoké úrovni, co se mezi těmito dvěma verzemi liší:

  • JUnit 5 je nyní zabalen v org.junit.jupiter skupina, která mění způsob, jakým ji zahrnete do svých projektů Maven a Gradle.
  • JUnit 4 vyžadoval minimální JDK 5 JDK; JUnit 5 vyžaduje minimálně 8 JDK.
  • JUnit 4's @Před, @Před hodinou, @Po, a @Po hodině poznámky byly nahrazeny @ Předtím každý, @BeforeAll, @AfterEach, a @Po všem, resp.
  • JUnit 4's @Ignorovat anotace byla nahrazena @ Zakázáno anotace.
  • The @Kategorie anotace byla nahrazena @Štítek anotace.
  • JUnit 5 přidává novou sadu metod tvrzení.
  • Běžci byly nahrazeny rozšířeními, s novým API pro implementátory rozšíření.
  • JUnit 5 zavádí předpoklady, které zastaví provádění testu.
  • JUnit 5 podporuje vnořené a dynamické testovací třídy.

Většinu těchto nových funkcí prozkoumáme v tomto článku.

Testování jednotky pomocí JUnit 5

Začněme jednoduše s příkladem end-to-end konfigurace projektu pro použití JUnit 5 pro test jednotky. Výpis 1 ukazuje a MathTools třída, jejíž metoda převede čitatele a jmenovatele na a dvojnásobek.

Výpis 1. Pří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ávratový (dvojitý) čitatel / (dvojitý) jmenovatel; }}

Máme dva primární scénáře pro testování MathTools třída a její metoda:

  • A platný test, ve kterém předáme nenulová celá čísla pro čitatele a jmenovatele.
  • A scénář selhání, ve kterém předáme nulovou hodnotu pro jmenovatele.

Výpis 2 zobrazuje testovací třídu JUnit 5 pro testování těchto dvou scénářů.

Výpis 2. Testovací třída JUnit 5 (MathToolsTest.java)

 balíček com.javaworld.geekcap.math; import java.lang.IllegalArgumentException; importovat org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; třída MathToolsTest {@Test void testConvertToDecimalSuccess () {double result = MathTools.convertToDecimal (3, 4); Assertions.assertEquals (0,75, výsledek); } @Test void testConvertToDecimalInvalidDenominator () {Assertions.assertThrows (IllegalArgumentException.class, () -> MathTools.convertToDecimal (3, 0)); }}

V seznamu 2 je testConvertToDecimalInvalidDenominator metoda provede MathTools :: convertToDecimal metoda uvnitř prosazovatVrhá volání. První argument je očekávaný typ výjimky, která má být vyvolána. Druhým argumentem je funkce, která vyvolá tuto výjimku. The prosazovat metoda provede funkci a ověří, že je vyvolán očekávaný typ výjimky.

Třída Assertions a její metody

Theorg.junit.jupiter.api.Test anotace označuje zkušební metodu. Všimněte si, že @Test anotace nyní pochází z balíčku JUnit 5 Jupiter API namísto JUnit 4 org.junit balík. The testConvertToDecimalSuccess metoda nejprve provede MathTools :: convertToDecimal metoda s čitatelem 3 a jmenovatelem 4, pak tvrdí, že výsledek je roven 0,75. The org.junit.jupiter.api. tvrzení třída poskytuje sadu statický metody pro porovnání skutečných a očekávaných výsledků. The Tvrzení třída má následující metody, které pokrývají většinu primitivních datových typů:

  • assertArrayEquals porovnává obsah skutečného pole s očekávaným.
  • assertEquals porovnává skutečnou hodnotu s očekávanou hodnotou.
  • assertNotEquals porovná dvě hodnoty, aby ověřil, že nejsou stejné.
  • tvrdit Pravda ověřuje, že zadaná hodnota je pravdivá.
  • assertFalse ověřuje, že zadaná hodnota je nepravdivá.
  • assertLinesMatch porovnává dva seznamy Tětivas.
  • assertNull ověřuje, že zadaná hodnota má hodnotu null.
  • assertNotNull ověřuje, že zadaná hodnota není null.
  • tvrditStejně ověřuje, že dvě hodnoty odkazují na stejný objekt.
  • assertNotSame ověřuje, že dvě hodnoty neodkazují na stejný objekt.
  • prosazovatVrhá ověřuje, že provedení metody vyvolá očekávanou výjimku (můžete to vidět v testConvertToDecimalInvalidDenominator příklad výše).
  • assertTimeout ověřuje, že se zadaná funkce dokončí v rámci zadaného časového limitu.
  • assertTimeout Preventivně ověřuje, že zadaná funkce se dokončí v rámci zadaného časového limitu, ale jakmile je časový limit dosažen, zabije provedení funkce.

Pokud některá z těchto metod tvrzení selže, je test jednotky označen jako neúspěšný. Toto oznámení o selhání se při spuštění testu zapíše na obrazovku a poté se uloží do souboru zprávy.

Použití delty s assertEquals

Při použití plovák a dvojnásobek hodnoty v an assertEquals, můžete také určit a delta což představuje hranici rozdílu mezi těmito dvěma. V našem příkladu jsme mohli přidat deltu 0,001, v případě, že 0,75 byla ve skutečnosti vrácena jako 0,750001.

Analýza výsledků testu

Kromě ověření hodnoty nebo chování, tvrdit metody mohou také přijmout textový popis chyby, který vám pomůže diagnostikovat selhání. Například:

 Assertions.assertEquals (0,75, výsledek, "Hodnota MathTools :: convertToDecimal nevrátila správnou hodnotu 0,75 pro 3/4"); Assertions.assertEquals (0,75, result, () -> "Hodnota MathTools :: convertToDecimal nevrátila správnou hodnotu 0,75 pro 3/4"); 

Výstup zobrazí očekávanou hodnotu 0,75 a skutečnou hodnotu. Zobrazí také zadanou zprávu, která vám pomůže pochopit kontext chyby. Rozdíl mezi těmito dvěma variantami spočívá v tom, že první vždy vytvoří zprávu, i když se nezobrazí, zatímco druhá vytvoří zprávu pouze v případě, že tvrzení selže. V tomto případě je konstrukce zprávy triviální, takže na tom nezáleží. Přesto není nutné sestavit chybovou zprávu pro test, který projde, takže je obvykle osvědčeným postupem použít druhý styl.

Nakonec, pokud používáte IDE jako IntelliJ ke spuštění testů, každá testovací metoda se zobrazí podle názvu metody. To je v pořádku, pokud jsou vaše názvy metod čitelné, ale můžete také přidat a @DisplayName anotace k vašim testovacím metodám pro lepší identifikaci testů:

@Test @DisplayName ("Testovat úspěšnou desetinnou konverzi") void testConvertToDecimalSuccess () {double result = MathTools.convertToDecimal (3, 4); Assertions.assertEquals (0,751, výsledek); }

Probíhá test jednotky

Chcete-li spustit testy JUnit 5 z projektu Maven, musíte zahrnout maven-surefire-plugin v Maven pom.xml soubor a přidat novou závislost. Výpis 3 ukazuje pom.xml soubor pro tento projekt.

Výpis 3. Maven pom.xml pro ukázkový projekt 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í své komponenty do org.junit.jupiter skupinu a musíme přidat junit-jupiter artefakt, což je artefakt agregátoru, který importuje následující závislosti:

  • junit-jupiter-api definuje API pro psaní testů a rozšíření.
  • junit-jupiter-engine je implementace testovacího stroje, která spouští jednotkové testy.
  • junit-jupiter-params poskytuje podporu pro parametrizované testy.

Dále musíme přidat maven-surefire-plugin vytvořte modul plug-in, aby bylo možné spustit testy.

Nakonec nezapomeňte zahrnout maven-compiler-plugin s verzí Java 8 nebo novější, takže budete moci používat funkce Java 8 jako lambdas.

Spusť to!

Pomocí následujícího příkazu spusťte testovací třídu z vašeho IDE nebo z Maven:

mvn čistý test

Pokud jste úspěšní, měli byste vidět výstup podobný tomuto:

 [INFO] ----------------------------------------------- -------- [INFO] TESTY [INFO] ----------------------------------- -------------------- [INFO] Spuštění com.javaworld.geekcap.math.MathToolsTest [INFO] Spuštění testů: 2, Selhání: 0, Chyby: 0, Přeskočeno : 0, Uplynulý čas: 0,04 s - v com.javaworld.geekcap.math.MathToolsTest [INFO] [INFO] Výsledky: [INFO] [INFO] Provedení testů: 2, Poruchy: 0, Chyby: 0, Přeskočeno: 0 [ INFO] [INFO] --------------------------------------------- --------------------------- [INFO] BUILD SUCCESS [INFO] --------------- -------------------------------------------------- ------- [INFO] Celkový čas: 3,832 s [INFO] Dokončeno: 2020-02-16T08: 21: 15-05: 00 [INFO] ------------- -------------------------------------------------- --------- 
$config[zx-auto] not found$config[zx-overlay] not found