Show Menu
Cheatography

JUnit 5 Cheat Sheet (DRAFT) by

JUnit5 Spickzettel

This is a draft cheat sheet. It is a work in progress and is not finished yet.

JUnit5 Grundlagen

Archit­ektur
JUnit 5 besteht aus 3 Teilen:
* Das Jupiter API für Testau­toren
* Das JUnit Platform Launcher API für BuildTools und IDE Integr­ation
* Das Test Engine SPI für andere Testing Framework

Test Engines
JUnit 5 besteht aus 2 Test-E­ngi­ne-­Imp­lem­ent­ier­ungen:
* Jupiter Engine zur Ausführung von JUnit 5 Testfällen
* Vintage Engine zur Ausführung von JUnit 3 oder JUnit 4 Testfällen
In einem Projekt kann entweder die eine oder die andere Engine oder beide zugleich zum Einsatz kommen.

Über die Vintage Engine bleibt die Möglic­hkeit Frameworks zu nutzen, welche nur das JUnit 4 API unters­tützen z.B. compil­e-t­esting.

Da im gleichen Projekt zusätzlich zur Vintage Engine auch die Jupiter Engine eingesetzt werden kann, können die eigenen Tests dann in JUnit 5 geschr­ieben werden und somit von den neuen Features provit­ieren.

Integr­ation in Build Tools
* Gradle ab 4.6
* Maven Surefire ab 2.22.0
* Ant ab 1.10.3

Integr­ation in IDEs
* IntelliJ IDEA ab 2016.2
* Eclipse ab 4.71a
* Visual Studio Code Java Testrunner ab 0.4.0
* Netbeans ab 10.0 (noch in Arbeit)
 

Features von JUnit 5

Features von JUnit 5

* Trennung der Testnamen von den Method­ennamen
Über @Displ­ayName lassen sich Sätze zur fachliche Testbe­zei­chnung festlegen. So können die Methoden immer noch alle mit testXXXX beginnen um in der Aufruf­hie­rarchie Testme­thoden sofort erkennen zu können. Im Report steht trotzdem ein sinnvoller fachlicher Name oder Satz welcher den Test beschr­eibt.

* Parame­ter­isierte Tests
Über @Param­ete­riz­edTest lassen sich parame­tri­sierte Tests erstellen. Bei diesen ist es möglich die Quelle der Parameter separat festzu­legen. Beispi­els­weise kann mit @CsvSource eine inline kommas­epa­rierte Liste als Datenq­uelle genutzt werden. Über @CsvFi­leS­ource lässt sich eine CSV Datei als Datenq­uelle nutzen und damit auch über diverse Tests sharen.
Allgemein ist es nicht notwendig aber wer möchte kann über @Conve­rtWith Konverter für den Dateni­mport verwenden. CSV ist nicht das einzige Format für Datenq­uellen, hier entstehen kontin­uie­rlich weitere.

* Dynamische Tests
Dynamische Tests sind eine neue Art von Tests im JUnit Universum. Über die @TestF­actory Annotation lassen sich dynamisch, zur Laufzeit Testfälle erzeugen. Wofür ist das gut? Angenommen wir haben 10 Tests geschr­ieben von denen jeder jeweils eine andere Eigens­chaft zur Barrie­ref­reiheit einer Webseite überprüft. Um diese Tests auf 3 Webseiten anzuwe­nden, müssten wir jeden der 10 Tests als parame­tri­sierten Test realis­ieren und stets eine Liste der 3 zu prüfenden Webseiten übergeben. Mit dynami­schen Tests kann man sich dieses Vorgehen sparen. Die Tests werden in einer Methode dynamisch zusamm­eng­ebaut per return Befehl an das Testfr­amework zurück gegeben. Dieses führt die Tests dann aus und lässt diese in Reports erscheinen als ob sie wie normale Tests geschr­ieben wurden.
Achtung: Die Lifecycle Methoden @Before, @Befor­eAll, @After, @AfterAll werden von dynamische Tests nicht berück­sic­htigt - bleiben also ohne Wirkung auf die dynami­schen Tests.
Eine sehr gute Einführung in das Thema findet sich man bei Baeldung

* Repeated Tests
Hierbei handelt es sich um eine weitere neue Art von Testfä­llen. Bei diesen kann über die Annotation @Repea­tedTest die Anzahl der Testau­sfü­hrungen angegeben werden. Denkbare Einsätze für diese Testart wären zur Realis­ierung von Zufall­stests (eine ergänzende Testart beim Modultest) oder zur Erkennung von Flacke­rtests. Falls man diese Art Teställe für Zufall­stests nutzt, sollte man darauf achten, dass die verwen­deten Testpa­rameter im Report ersche­inen, da sonst bei der Auswertung nicht klar ist unter welchen Beding­ungen der Test fehl geschlagen ist.

* Extensions
In JUnit 5 wurde das Konzept der @RunWith und @Rule Erweit­erungen durch das Konzept der @Exten­dWith ersetzt. Der Vorteil ist ein nun einhei­tliches Konzept zur Erweit­erung. Extensions lassen sich verstehen wie Plugins welche bestimmte Extensions Points des JUnit 5 Frameworks erweitern. In der Regel nutzen Frameworks wie Mockito, Spring, Testco­nta­iners, Wiremock, Kafka und viele mehr diese Schnit­tstelle aber natürlich kann man auch selbst hierüber das Framework erweitern. Zur Erweit­erung stehen folgende Arten zur Verfügung:
** Verarb­eitung der Testin­stanz nach Testau­sfü­hrung
** Bedingte Testau­sfü­hrung
** Lifecycle Callbacks
** Parame­ter­auf­lösung
** Exception handling
Ein sehr guter Einstieg in dieses Thema findes sich wieder bei Baeldung

* Kotlin Styled Tests
Um ein Feeling von Kotlin in das JUnit Framework zu bringen wurden folgende Neuerungen eingef­ührt:
* @TestI­nst­anc­e(L­ife­cyc­le.P­ER­_CLASS) Alle Testfälle teilen sich die gleiche Testsi­nstanz
* assertAll und assert­Throw

* Parallele Testau­sfü­hrung
Mit Hilfe des junit.j­up­ite­r.e­xec­uti­on.p­ar­all­el.e­nabled Konfig­ura­tio­nsp­ara­meters kann dem Framework mitgeteilt werden, dass alle Testfälle parallel ausgeführt werden sollen. Weiterhin kann einges­tellt werden, wieviel maximal parallel ausgeführt werden.
Da in der Regel nicht alle Testfälle eine parallele Ausführung vertrage, kann per @Excec­ution Annotation festgelegt werden, welche Testfälle im gleichen Thread ausgeführt werden sollen. Um bei der parallelen Ausführung nicht in Deadlocks zu laufen, kann per @Resou­rceLock Annotation beschr­ieben werden, auf welche Resourcen ein Testfall lesend oder schreibend zugreift. JUnit sorgt dann dafür, dass Testfälle mit ungüns­tiger Kombin­ation (schre­ibe­nd/­lesend) nicht zu gleich ausgeführt werden.

* Warum sollte ich von JUnit 4 umsteigen?
* Möglic­her­weise wolltest Du schon immer einmal fachliche Sätze in Deinen Testre­ports sehen - das geht jetzt.
* Du wolltest einen Spring­-Boot Tests als Parame­tri­sierten Test ausführen und dabei keine super kniffligen Worarounds verstehen - das geht jetzt.
* Du wolltest schon mal zwei @RunWith Annota­tionen an einer Testklasse befestigen und hast gemerkt, dass das nicht geht? Mit Extensions geht es jetzt.
* Du wolltest letztens Deine Testfälle direkt aus der Testin­stanz ableiten und dynamisch erstellen aber es ging nicht - jetzt kannst Du @TestF­actory nutzen.
* Die Laufzeit Deiner Tests ist extrem lang weil Du viele kleine Tests hast, die eigentlich auf dem selben Objekt arbeiten könnten ohne sich zu stören aber JUnit 4 baut jedes Mal eine neue isolierte Umgebung auf und das dauert - jetzt kannst Du @TestI­nst­anc­e(L­ife­cyc­le.P­ER­_CLASS) nutzen
* Du wolltests schon immer Deine Tests mit diversen Tags versehen und dann selbst per Tagauswahl entsch­eiden welche Tests zur Ausführung kommen - das geht jetzt.
* Du wolltest schon immer Lambda Ausdrücke und andere Java 8 Features im JUnit Test nutzen - das geht jetzt.
* Du brauchst JUnit 4 weiterhin weil ein Framework das Du nutzt nicht mehr weiter­ent­wickelt wird und nur mit JUnit 4 klar kommt - JUnit 5 ist kompatible über die Vintage Engine. Du kannst JUnit 5 und JUnit 4 Testfälle in einem Projekt realis­ieren ohne störende Nebenw­irk­ungen.