JUnit Förväntat undantagstest: @Test(förväntat)

⚡ Smart sammanfattning

JUnit undantagstestning bekräftar att en metod kastar det fel den ska kasta, med hjälp av den valfria förväntade parametern i @Test-annoteringen i JUnit 4 och assertThrows-metoden i JUnit 5.

  • 🔘 Syfte: Bevisa att ogiltig inmatning producerar det dokumenterade undantaget istället för ett tyst felaktigt svar.
  • ☑️ Syntax: @Test(expected = ArithmeticException.class) godkänns endast när exakt den undantagstypen utlöses.
  • Exempel: JUnitMeddelandet dividerar med noll, och AirthematicTest förväntar sig den resulterande ArithmeticException.
  • 🧪 alternativ: Ett try-block följt av fail() låter dig inspektera det fångade undantaget innan du gör en assertion på det.
  • 🛠️ JUnit 5: assertThrows returnerar det fångade undantaget, så att meddelandet och orsaken också kan hävdas.
  • 📌 Fälla: Den förväntade parametern skickas varhelst undantaget inträffar, vilket kan dölja ett fel i installationskoden.

JUnit förväntat undantagstest med parametern @Test(förväntad)

JUnit ger möjlighet att trace undantaget och även för att kontrollera om koden utlöser det förväntade undantaget eller inte.

JUnit 4 erbjuder ett enkelt och lättläst sätt att testa undantag. Du kan använda:

  • Den valfria parametern (förväntad) för @Test-annoteringoch
  • Till tracinformationen kan ”fail()” användas.

Medan testning ett undantag måste du se till att undantagsklassen du anger i den valfria parametern för @Test-annotering är samma som metoden faktiskt kastar. Detta beror på att du förväntar dig ett undantag från metoden du enhetstestning; annars vår JUnit testet skulle misslyckas.

Exempel: @Test(förväntat = IllegalArgumentException.class)

Genom att använda parametern ”expected” kan du ange undantagsnamnet som vårt test kan utlösa. I exemplet ovan använder du ”Ogiltigt argumentundantag", vilket kommer att utlösas av testet om en utvecklare använder ett argument som inte är tillåtet.

Exempel med @Test(förväntat)

Låt oss förstå undantagstestning genom att skapa en Java klass med en metod som kastar en undantagDu kommer att hantera det och testa det i en testklass. Överväg JUnitMessage.java, som har en metod som utför en matematisk operation. Divisionen på rad 14 dividerar med noll, så metoden utlöser alltid ett "ArithmeticException". Se nedan:

JUnitMeddelandeklass i Eclipse med printMessage dividerande med noll på rad 14

package guru99.junit;

public class JUnitMessage{

	private String message;

	public JUnitMessage(String message) {
		this.message = message;
	}

public void printMessage(){

	System.out.println(message); 
	int divide=1/0;

}

public String printHiMessage(){ 

	message="Hi!" + message;
	
	System.out.println(message);

	return message;
}

}

Code Förklaring:

  • Code Linje 7: Skapa en parametriserad konstruktor med fältinitiering.
  • Code Rad 11-14: Skapa en metod för den matematiska operationen.
  • Code Linje 18: Skapar en annan metod för att skriva ut ett meddelande.
  • Code Linje 20: Skapa en ny sträng för att skriva ut ett meddelande.
  • Code Linje 22: Skriver ut det nya meddelandet som skapades på rad 20.

Låt oss skapa en testklass för ovanstående Java klass för att verifiera undantaget.

Se nedan testklassen som enhetstestar undantaget (här ArithmeticException) som genereras från ovanstående. Java klass:

AirthematicTest.java

Skärmdumpen nedan visar samma test i editorn, där filen sparas som AirthematicTest1, med den förväntade parametern markerad på rad 13:

AirthematicTest1 klass i Eclipse med @Test(förväntat = ArithmeticException.class) markerat på rad 13

package guru99.junit;

import static org.junit.Assert.assertEquals;

import org.junit.Test;

public class AirthematicTest {

	public String message = "Saurabh";
	
	JUnitMessage junitMessage = new JUnitMessage(message);
	
	@Test(expected = ArithmeticException.class)
	public void testJUnitMessage(){

		System.out.println("Junit Message is printing ");
		junitMessage.printMessage();

	}

	@Test
	public void testJUnitHiMessage(){ 
		message="Hi!" + message;
		System.out.println("Junit Message is printing ");
		assertEquals(message, junitMessage.printHiMessage());
	
	}
}

Code Förklaring:

  • Code Linje 13: Använder @Test-annoteringen för att skapa vårt test. När du kör metoden i klassen ovan kommer den att anropa en matematisk operation. Här förväntas ArithmeticException, så du listar den som en parameter i @Test.
  • Code Linje 17: Anropar printMessage() från JUnitMessage.java.
  • Code Rad 21-22: Skapar ytterligare en testmetod för att kontrollera Hi-meddelandet, den här gången utan en förväntad parameter.

Klassen innehåller två testmetoder, så en enda körning kör båda: den som förväntar sig ArithmeticException och den som assertar på den returnerade strängen.

Obs: Detta exempel används under tre namn i originalmaterialet — listan anropar klassen AirthematicTest, redigerarens skärmdump visar AirthematicTest1 och resultatvyn rapporterar JunitTestExample. Koden är identisk i varje; endast filnamnet skiljer sig åt.

Låt oss utföra det och verifiera resultatet. JUnit se nedan rapporterar förloppet av JunitTestExample.java.

Produktion:

Här är utdata, som visar ett lyckat test utan fel trace enligt nedan:

Eclipse JUnit visa rapportering Körningar 2/2 med noll fel och noll misslyckanden för JunitTestExample

Båda metoderna är gröna. Den första går igenom eftersom det deklarerade ArithmeticException faktiskt anlände, och den andra går igenom eftersom den returnerade strängen matchade. Om divisionen aldrig hade kastats, JUnit skulle ha misslyckats med den första metoden med meddelandet "Förväntat undantag: java.lang.ArithmeticException".

Tre sätt att testa ett undantag i JUnit 4

Den förväntade parametern är den kortaste av de tre JUnit 4 idiom, men det är inte alltid det rätta. Tabellen jämför dem utifrån de två frågor som avgör valet: kan du hävda dig på budskapet, och vet du vilken rad som kastades?

Tillvägagångssätt Hävdar budskapet? Fäster kastlinjen? Bäst för
@Test(förväntad = X.klass) Nej Nej — vilken rad som helst i metoden kan kasta Korta tester där endast undantagstypen spelar roll.
försök / misslyckas() / fånga Ja, inuti fångstblocket Ja — endast det bevakade samtalet bevakas Tester som måste inspektera meddelandet eller orsaken.
@Regel FörväntatUndantag Ja, via expectMessage() Nej Äldre sviter byggda redan enligt regler.

Idiomet fail() som nämns i inledningen ser ut så här. Om anropet inte utlöser något, körs fail() och testet rapporterar meddelandet du skrev:

@Test
public void testDivideByZero() {
    try {
        junitMessage.printMessage();
        fail("Expected an ArithmeticException");
    } catch (ArithmeticException e) {
        assertEquals("/ by zero", e.getMessage());
    }
}

Regeln ExpectedException ligger mellan de två. Den föråldrades i JUnit 4.13 till förmån för assertThrows-metoden som beskrivs härnäst, så ny JUnit 4 tester bör inte använda det.

Hur man testar undantag i JUnit 5 med assertThrows()

JUnit 5 tar bort den förväntade parametern helt och hållet från @Test. Jupiter tillhandahåller assertThrows(), som tar undantagsklassen och en lambda som innehåller koden under test. Den returnerar undantaget den fångade, så att meddelandet, orsaken och eventuella anpassade fält kan bekräftas efteråt.

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import org.junit.jupiter.api.Test;

public class AirthematicJupiterTest {

    JUnitMessage junitMessage = new JUnitMessage("Saurabh");

    @Test
    public void testJUnitMessage() {
        ArithmeticException thrown = assertThrows(
                ArithmeticException.class,
                () -> junitMessage.printMessage());
        assertEquals("/ by zero", thrown.getMessage());
    }
}

Tre relaterade påståenden komplettera familjen:

  • hävdaKast accepterar undantagstypen eller någon underklass av den.
  • hävdaKastaExakt förkastar en underklass, så endast den namngivna typen godkänns.
  • hävdarKastaInte anger den motsatta förväntan, att blocket slutförs rent.

Ocuco-landskapet JUnit 4-koden på den här sidan körs fortfarande på JUnit Plattform genom den gamla motorn, så inget ovanför behöver skrivas om för att fortsätta fungera medan ett projekt migreras.

Vanliga misstag vid testning av undantag i JUnit

Undantagstester misslyckas på ett litet antal igenkännbara sätt. Varje rad anger symptom, orsak och lösning.

Symptom Orsak Fast
Förväntat undantag: java.lang.ArithmeticException Metoden slutfördes utan att kasta. Kontrollera att inmatningen verkligen är ogiltig och kör sedan om.
Testet klarade det men fel linje kastades Den förväntade parametern övervakar hela metoden, inklusive installationsprogrammet. Flytta ut installationsprogrammet, eller växla till assertThrows runt ett anrop.
Ohanterad undantagstyp i redigeraren Ett kontrollerat undantag utlöses men deklareras aldrig. Lägg till kast i testmetodens signatur.
Testet klarar en underklass som du inte avsåg assertThrows accepterar underklasser av den namngivna typen. Använd assertThrowsExactly för en strikt typmatchning.
förväntat är inte ett giltigt attribut Testet kompilerades mot Jupiter @Test-annoteringen. Importera org.junit.Test för JUnit 4, eller flytta till assertThrows.

Den sista raden är den som fångar de flesta mitt under migreringen, eftersom båda annoteringarna heter @Test och det är bara importen som skiljer dem åt.ping ett JUnit version per testfall klassen undviker hela klassproblemet.

Vanliga frågor

Den förväntade parametern kan inte kontrollera ett meddelande. Slå in anropet i ett try-block, anropa fail() omedelbart efter det och anropa getMessage() inuti catch-blocket. JUnit 5 gör detta enklare eftersom assertThrows returnerar det fångade undantaget.

JUnit misslyckas med testet och rapporterar "Förväntat undantag" följt av klassen du namngav. Inget annat rapporteras, så ett test som aldrig utlöser ett fel ser identiskt ut med ett vars produktionskod tyst ändrade beteende.

AI-assistenter läser en metod, listar indata som når varje throw-sats och utarbetar ett test per gren. Behandla utdata som en utgångspunkt: assistenten härleder undantagstypen från koden, så ett felaktigt throw-uttryck kopieras korrekt till testet.

Copilot följer den stil som redan finns i filen, så ett blandat projekt får en blandning. Kontrollera importraden innan du accepterar ett förslag, eftersom org.junit.Test och org.junit.jupiter.api.Test ser identiska ut i editorn.

Den finns fortfarande kvar, men den avvecklades år JUnit 4.13 och aldrig portad till Jupiter. Befintliga programsviter kan behålla den; nya tester bör använda assertThrows, som läser bättre och inte behöver ett publikt regelfält.

Ja. Lambda-parametern är en körbar fil, som deklareras att kasta en Throwable, så ett kontrollerat undantag behöver ingen throws-klausul i själva testmetoden. Detsamma gäller för JUnit 4 försöka fånga idiom.

assertThrows accepterar vilken underklass som helst av den typ du namnger, så att förvänta sig RuntimeException skickar även vidare NullPointerException. Använd assertThrowsExactly när den exakta klassen är viktig, eller namnge den smalaste typen du faktiskt förväntar dig.

Endast där undantaget är en del av villkorettract. Vid testning av ett undantag lovar metoden aldrig att låsa ett oavsiktligt beteende och gör refaktorering svårare, vilket omintetgör poängen med testet.

Sammanfatta detta inlägg med: