Gids voor JUnit 4-regels

1. Overzicht

In deze zelfstudie gaan we de functie Regels bekijken die wordt geboden door de JUnit 4-bibliotheek.

We beginnen met de introductie van het JUnit-regelsmodel voordat we de belangrijkste basisregels van de distributie doornemen. Bovendien zullen we ook zien hoe we onze eigen aangepaste JUnit-regel kunnen schrijven en gebruiken.

Bekijk onze uitgebreide JUnit-serie voor meer informatie over testen met JUnit.

Merk op dat als u JUnit 5 gebruikt, de regels zijn vervangen door het uitbreidingsmodel.

2. Inleiding tot de regels van JUnit 4

JUnit 4-regels bieden een flexibel mechanisme om tests te verbeteren door wat code uit te voeren rond de uitvoering van een testcase. In zekere zin lijkt het op hebben @Voordat en @Na annotaties in onze testklasse.

Laten we ons voorstellen dat we tijdens het instellen van de test verbinding wilden maken met een externe bron, zoals een database, en vervolgens de verbinding wilden sluiten nadat onze test is voltooid. Als we die database in meerdere tests willen gebruiken, zouden we die code in elke test dupliceren.

Door een regel te gebruiken, kunnen we alles op één plek geïsoleerd hebben en de code uit meerdere testklassen gemakkelijk hergebruiken.

3. JUnit 4-regels gebruiken

Dus hoe kunnen we regels gebruiken? We kunnen JUnit 4-regels gebruiken door deze eenvoudige stappen te volgen:

  • Voeg een ... toe openbaar veld naar onze testklasse en zorg ervoor dat het type van dit veld een subtype is van de org.junit.rules.TestRule koppel
  • Annoteer het veld met de @Regel annotatie

In de volgende sectie zullen we zien welke projectafhankelijkheden we nodig hebben om aan de slag te gaan.

4. Maven afhankelijkheden

Laten we eerst de projectafhankelijkheden toevoegen die we nodig hebben voor onze voorbeelden. We hebben alleen de JUnit 4-hoofdbibliotheek nodig:

 junit junit 4.12 

Zoals altijd kunnen we de nieuwste versie van Maven Central krijgen.

5. Regels in de distributie

Natuurlijk, JUnit biedt een aantal handige, vooraf gedefinieerde regels als onderdeel van de bibliotheek. We kunnen al deze regels vinden in het org.junit.rules pakket.

In dit gedeelte zullen we enkele voorbeelden zien van hoe u ze kunt gebruiken.

5.1. De Tijdelijke map Regel

Bij het testen hebben we vaak toegang nodig tot een tijdelijk bestand of map. Het beheer van het maken en verwijderen van deze bestanden kan echter omslachtig zijn. De ... gebruiken Tijdelijke map regel, kunnen we het maken van bestanden en mappen beheren die moeten worden verwijderd wanneer de testmethode wordt beëindigd:

@Rule public TemporaryFolder tmpFolder = new TemporaryFolder (); @Test openbare ongeldig gegevenTempFolderRule_whenNewFile_thenFileIsCreated () gooit IOException {File testFile = tmpFolder.newFile ("test-file.txt"); assertTrue ("Het bestand zou aangemaakt moeten zijn:", testFile.isFile ()); assertEquals ("Tijdelijke map en testbestand moeten overeenkomen met:", tmpFolder.getRoot (), testFile.getParentFile ()); }

Zoals we kunnen zien, definiëren we eerst de Tijdelijke map regel tmpFolder. Vervolgens maakt onze testmethode een bestand aan met de naam test-bestand.txt in de tijdelijke map. We controleren vervolgens of het bestand is gemaakt en bestaat waar het hoort. Echt leuk en simpel!

Wanneer de test is voltooid, moeten de tijdelijke map en het bestand worden verwijderd. Deze regel controleert echter niet of het verwijderen is gelukt.

Er zijn ook een paar andere interessante methoden die het vermelden waard zijn in deze klasse:

  • nieuw bestand()

    Als we geen bestandsnaam opgeven, maakt deze methode een nieuw bestand met een willekeurige naam.

  • newFolder (String ... folderNames)

    Om recursief diepe tijdelijke mappen te maken, kunnen we deze methode gebruiken.

  • nieuwe map ()

    Evenzo is het nieuwe map () methode maakt een nieuwe map met een willekeurige naam aan.

Een leuke toevoeging die het vermelden waard is, is dat vanaf versie 4.13 de Tijdelijke map regel staat verificatie van verwijderde bronnen toe:

@Rule openbare TemporaryFolder-map = TemporaryFolder.builder (). AssureDeletion (). Build ();

Als een bron niet kan worden verwijderd, mislukt de test met een AssertionFout.

Ten slotte kunnen we in JUnit 5 dezelfde functionaliteit bereiken met de Temporary Directory-extensie.

5.2. De ExpectedException Regel

Zoals de naam al doet vermoeden, we kunnen de ExpectedException regel om te verifiëren dat bepaalde code een verwachte uitzondering genereert:

@Rule openbare finale ExpectedException gegooid = ExpectedException.none (); @Test openbare ongeldige gegevenIllegalArgument_whenExceptionThrown_MessageAndCauseMatches () {Throwwn.expect (IllegalArgumentException.class); gegooid.expectCause (isA (NullPointerException.class)); throwwn.expectMessage ("Dit is illegaal"); gooi nieuwe IllegalArgumentException ("Dit is illegaal", nieuwe NullPointerException ()); }

Zoals we in het bovenstaande voorbeeld kunnen zien, verklaren we eerst de ExpectedException regel. Vervolgens stellen we in onze test dat een IllegalArgumentException wordt gegooid.

Met behulp van deze regel kunnen we ook enkele andere eigenschappen van de uitzondering verifiëren, zoals het bericht en de oorzaak.

Voor een uitgebreide gids voor het testen van uitzonderingen met JUnit, bekijk onze uitstekende gids over het beweren van een uitzondering.

5.3. De Test naam Regel

Simpel gezegd, de Test naam regel geeft de huidige testnaam binnen een bepaalde testmethode:

@Rule openbare testnaam naam = nieuwe testnaam (); @Test openbare ongeldig gegevenAddition_whenPrintingTestName_thenTestNameIsDisplayed () {LOG.info ("Uitvoeren: {}", name.getMethodName ()); assertEquals ("givenAddition_whenPrintingTestName_thenTestNameIsDisplayed", name.getMethodName ()); }

In dit triviale voorbeeld, wanneer we de unit-test uitvoeren, zouden we de testnaam in de uitvoer moeten zien:

INFO c.baeldung.rules.JUnitRulesUnitTest - Uitvoeren: gegevenAddition_whenPrintingTestName_thenTestNameIsDisplayed

5.4. De Time-out Regel

In dit volgende voorbeeld kijken we naar de Time-out regel. Deze regel biedt een handig alternatief voor het gebruik van de time-outparameter op een individuele testannotatie.

Laten we nu eens kijken hoe we deze regel kunnen gebruiken om een ​​algemene time-out in te stellen voor alle testmethoden in onze testklasse:

@Rule openbare time-out globalTimeout = Timeout.seconds (10); @Test openbare leegte gegevenLongRunningTest_whenTimout_thenTestFails () gooit InterruptedException {TimeUnit.SECONDS.sleep (20); }

In het bovenstaande triviale voorbeeld, we definiëren eerst een globale time-out voor alle testmethoden van 10 seconden. Vervolgens definiëren we bewust een test die langer dan 10 seconden duurt.

Wanneer we deze test uitvoeren, zouden we een testfout moeten zien:

org.junit.runners.model.TestTimedOutException: test time-out na 10 seconden ...

5.5. De ErrorCollector Regel

Vervolgens gaan we de ErrorCollector regel. Met deze regel kan de uitvoering van een test worden voortgezet nadat het eerste probleem is gevonden.

Laten we eens kijken hoe we deze regel kunnen gebruiken om alle fouten te verzamelen en ze allemaal tegelijk te rapporteren wanneer de test wordt beëindigd:

@Rule openbare finale ErrorCollector errorCollector = nieuwe ErrorCollector (); @Test openbare leegte gegevenMultipleErrors_whenTestRuns_thenCollectorReportsErrors () {errorCollector.addError (nieuwe Throwable ("Het eerste ging fout!")); errorCollector.addError (nieuwe Throwable ("Er ging iets mis!")); errorCollector.checkThat ("Hallo wereld", niet (bevatString ("ERROR!"))); }

In het bovenstaande voorbeeld voegen we twee fouten toe aan de verzamelaar. Als we de test uitvoeren, gaat de uitvoering door, maar de test zal aan het einde mislukken.

In de uitvoer zullen we beide gerapporteerde fouten zien:

java.lang.Throwable: Het eerste wat er mis ging! ... java.lang.Throwable: Er ging nog iets mis!

5.6. De Verificateur Regel

De Verificateur rule is een abstracte basisklasse die we kunnen gebruiken als we wat aanvullend gedrag van onze tests willen verifiëren. In feite is de ErrorCollector regel die we in de laatste sectie zagen, breidt deze klasse uit.

Laten we nu eens kijken naar een triviaal voorbeeld van het definiëren van onze eigen verificateur:

privélijst messageLog = nieuwe ArrayList (); @Rule public Verifier verifier = nieuwe Verifier () {@Override public void verify () {assertFalse ("Berichtenlogboek is niet leeg!", MessageLog.isEmpty ()); }}; 

Hier definiëren we een nieuw Verificateur en negeer de verifiëren() methode om wat extra verificatielogica toe te voegen. In dit eenvoudige voorbeeld controleren we eenvoudig of het berichtenlogboek in ons voorbeeld niet leeg is.

Als we nu de unit-test uitvoeren en een bericht toevoegen, zouden we moeten zien dat onze verificator is toegepast:

@Test openbare leegte gegevenNewMessage_whenVerified_thenMessageLogNotEmpty () {// ... messageLog.add ("Er is een nieuw bericht!"); }

5.7. De DisableOnDebug Regel

Soms willen we een regel uitschakelen tijdens het debuggen. Het is bijvoorbeeld vaak wenselijk om een Time-out regel bij het debuggen om te voorkomen dat onze test een time-out krijgt en mislukt voordat we tijd hebben gehad om het correct te debuggen.

De DisableOnDebug Rule doet precies dit en stelt ons in staat om bepaalde regels te labelen die moeten worden uitgeschakeld bij het debuggen:

@Rule openbaar DisableOnDebug disableTimeout = nieuw DisableOnDebug (Timeout.seconds (30));

In het bovenstaande voorbeeld kunnen we zien dat om deze regel te gebruiken, we geven gewoon de regel die we willen uitschakelen door aan de constructor.

Het belangrijkste voordeel van deze regel is dat we regels kunnen uitschakelen zonder wijzigingen aan te brengen in onze testklassen tijdens het debuggen.

5.8. De ExternalResource Regel

Bij het schrijven van integratietests willen we meestal een externe bron instellen voor een test en deze daarna afbreken. Gelukkig biedt JUnit hiervoor nog een handige basisklasse.

We kunnen de abstracte klasse uitbreiden ExternalResource om een ​​externe bron voor een test in te stellen, zoals een bestand of een databaseverbinding. In feite is de Tijdelijke map regel die we eerder zagen, strekt zich uit ExternalResource.

Laten we snel kijken hoe we deze klasse kunnen uitbreiden:

@Rule public final ExternalResource externalResource = new ExternalResource () {@Override protected void before () gooit Throwable {// code om een ​​specifieke externe bron in te stellen. }; @Override protected void after () {// code om de externe bron af te breken}; };

Als we in dit voorbeeld een externe bron definiëren, hoeven we alleen maar de voordat() methode en na() methode om onze externe bron op te zetten en af ​​te breken.

6. Klassenregels toepassen

Tot nu toe zijn alle voorbeelden die we hebben bekeken, toegepast op methoden voor afzonderlijke testcases. Soms willen we echter een regel toepassen op testklasniveau. We kunnen dit bereiken door de @ClassRule annotatie.

Deze annotatie werkt op dezelfde manier als @Regel maar wikkelt een regel rond een hele test - het belangrijkste verschil is dat het veld dat we gebruiken voor onze klassenregel statisch moet zijn:

@ClassRule openbare statische TemporaryFolder globalFolder = nieuwe TemporaryFolder ();

7. Een aangepaste JUnit-regel definiëren

Zoals we hebben gezien, biedt JUnit 4 een aantal handige regels uit de doos. Natuurlijk kunnen we onze eigen aangepaste regels definiëren. Om een ​​aangepaste regel te schrijven, moeten we de Testregel koppel.

Laten we eens kijken naar een voorbeeld van het definiëren van een aangepaste regel voor de naamregistratie van een testmethode:

openbare klasse TestMethodNameLogger implementeert TestRule {privé statische laatste Logger LOG = LoggerFactory.getLogger (TestMethodNameLogger.class); @Override public Statement apply (Statement base, Description description) {logInfo ("Before test", description); probeer {return new Statement () {@Override public void evalu () gooit Throwable {base.evaluate (); }}; } tenslotte {logInfo ("Na test", beschrijving); }} private void logInfo (String msg, Description description) {LOG.info (msg + description.getMethodName ()); }}

Zoals we kunnen zien, is de Testregel interface bevat een methode genaamd toepassen (verklaring, beschrijving) die we moeten overschrijven om een ​​exemplaar van te retourneren Uitspraak. De verklaring vertegenwoordigt onze tests binnen de JUnit-runtime. Als we de evalueren () methode, dit voert onze test uit.

In dit voorbeeld loggen we een voor en na bericht en nemen we op vanuit de Omschrijving object de naam van de methode van de individuele test.

8. Regelketens gebruiken

In dit laatste gedeelte bekijken we hoe we verschillende testregels kunnen bestellen met behulp van de RuleChain regel:

@Rule openbare RuleChain chain = RuleChain.outerRule (nieuwe MessageLogger ("Eerste regel")) .around (nieuwe MessageLogger ("Tweede regel")) .around (nieuwe MessageLogger ("Derde regel"));

In het bovenstaande voorbeeld maken we een reeks van drie regels die eenvoudig het bericht afdrukken dat aan elk is doorgegeven MessageLogger constructeur.

Als we onze test uitvoeren, zullen we zien hoe de ketting in de volgende volgorde wordt aangebracht:

Starten: eerste regel Starten: tweede regel Starten: derde regel Voltooid: derde regel Voltooid: tweede regel Voltooid: eerste regel

9. Conclusie

Samenvattend hebben we in deze tutorial de regels van JUnit 4 in detail onderzocht.

Allereerst hebben we uitgelegd wat regels zijn en hoe we ze kunnen gebruiken. Vervolgens hebben we dieper ingegaan op de regels die deel uitmaken van de JUnit-distributie.

Ten slotte hebben we gekeken hoe we onze eigen aangepaste regel kunnen definiëren en hoe we regels aan elkaar kunnen koppelen.

Zoals altijd is de volledige broncode van het artikel beschikbaar op GitHub.