JUnit Forventet undtagelsestest: @Test(forventet)

โšก Smart opsummering

JUnit Undtagelsestest bekrรฆfter, at en metode kaster den fejl, den skal kaste, ved hjรฆlp af den valgfri forventede parameter i @Test-annotationen i JUnit 4 og assertThrows-metoden i JUnit 5.

  • ๐Ÿ”˜ Formรฅl: Bevis at ugyldigt input producerer den dokumenterede undtagelse i stedet for et tavst forkert svar.
  • โ˜‘๏ธ Syntaks: @Test(expected = ArithmeticException.class) bestรฅr kun, nรฅr den prรฆcise undtagelsestype udlรธses.
  • โœ… Eksempel: JUnitBeskeden dividerer med nul, og AirthematicTest forventer den resulterende ArithmeticException.
  • ๐Ÿงช Alternativ: En try-blok efterfulgt af fail() lader dig inspicere den fangede undtagelse, fรธr du foretager en assertion pรฅ den.
  • ๐Ÿ› ๏ธ JUnit 5: assertThrows returnerer den fangede undtagelse, sรฅ meddelelsen og รฅrsagen ogsรฅ kan hรฆvdes.
  • ๐Ÿ“Œ Faldgrube: Den forventede parameter overfรธres, uanset hvor undtagelsen opstรฅr, hvilket kan skjule en fejl i opsรฆtningskoden.

JUnit forventet undtagelsestest ved hjรฆlp af @Test(forventet) parameteren

JUnit giver mulighed for at trace undtagelsen og ogsรฅ for at kontrollere, om koden kaster den forventede undtagelse eller ej.

JUnit 4 giver en nem og lรฆsbar metode til undtagelsestestning. Du kan bruge:

  • Den valgfrie parameter (forventet) for @Test-annoteringog
  • Til tracHvis informationen er korrekt, kan โ€œfail()โ€ bruges.

Mens test en undtagelse, skal du sikre dig, at den undtagelsesklasse, du angiver i den valgfri parameter for @Test-annotering er den samme, som metoden rent faktisk kaster. Dette skyldes, at du forventer en undtagelse fra den metode, du enhedstest; ellers vores JUnit test ville mislykkes.

Eksempel: @Test(forventet = IllegalArgumentException.class)

Ved at bruge parameteren "forventet" kan du angive navnet pรฅ den undtagelse, som vores test kan kaste. I eksemplet ovenfor bruger du "Ulovligt argumentundtagelse", som vil blive kastet af testen, hvis en udvikler bruger et argument, der ikke er tilladt.

Eksempel med @Test(forventet)

Lad os forstรฅ undtagelsestestning ved at oprette en Java klasse med en metode, der kaster en undtagelseDu skal hรฅndtere det og teste det i en testklasse. Overvej JUnitMessage.java, som har en metode, der udfรธrer en matematisk operation. Divisionen pรฅ linje 14 dividerer med nul, sรฅ metoden kaster altid en "ArithmeticException". Se nedenfor:

JUnitBeskedklasse i Eclipse med printMessage dividering med nul pรฅ linje 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 Forklaring:

  • Code Linje 7: Oprettelse af en parameteriseret konstruktรธr med feltinitialisering.
  • Code Linje 11-14: Oprettelse af en metode til den matematiske operation.
  • Code Linje 18: Oprettelse af en anden metode til at udskrive en meddelelse.
  • Code Linje 20: Oprettelse af en ny streng for at udskrive en besked.
  • Code Linje 22: Udskriver den nye besked oprettet i linje 20.

Lad os oprette en testklasse til ovenstรฅende Java klasse for at verificere undtagelsen.

Se nedenfor testklassen, der enhedstester undtagelsen (her ArithmeticException), som udlรธses ovenfra. Java klasse:

AirthematicTest.java

Skรฆrmbilledet nedenfor viser den samme test i editoren, hvor filen er gemt som AirthematicTest1, med den forventede parameter fremhรฆvet pรฅ linje 13:

AirthematicTest1 klasse i Eclipse med @Test(forventet = ArithmeticException.class) fremhรฆvet pรฅ linje 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 Forklaring:

  • Code Linje 13: Brug af @Test-annotationen til at oprette vores test. Nรฅr du udfรธrer metoden i klassen ovenfor, vil den kalde en matematisk operation. Her forventes ArithmeticException, sรฅ du angiver den som en parameter i @Test.
  • Code Linje 17: Aktivering af printMessage() fra JUnitMessage.java.
  • Code Linje 21-22: Opretter endnu en testmetode til at kontrollere Hi-meddelelsen, denne gang uden en forventet parameter.

Klassen indeholder to testmetoder, sรฅ en enkelt kรธrsel udfรธrer dem begge: den, der forventer ArithmeticException, og den, der assert pรฅ den returnerede streng.

Bemรฆrk: Dette eksempel bruges under tre navne i det originale materiale โ€” listen kalder klassen AirthematicTest, skรฆrmbilledet i redigeringsprogrammet viser AirthematicTest1, og resultatvisningen rapporterer JunitTestExample. Koden er identisk i begge; kun filnavnet er forskelligt.

Lad os udfรธre det og verificere resultatet. JUnit se nedenstรฅende rapporter om forlรธbet af JunitTestExample.java.

Output:

Her er outputtet, som viser en vellykket test uden fejl trace som angivet nedenfor:

Eclipse JUnit se rapportering Kรธrer 2/2 med nul fejl og nul fejl for JunitTestExample

Begge metoder er grรธnne. Den fรธrste bestรฅs, fordi den ArithmeticException, den erklรฆrede, faktisk ankom, og den anden bestรฅs, fordi den returnerede streng matchede. Hvis divisionen aldrig var blevet kastet, JUnit ville have fejlet den fรธrste metode med meddelelsen "Forventet undtagelse: java.lang.ArithmeticException".

Tre mรฅder at teste en undtagelse pรฅ JUnit 4

Den forventede parameter er den korteste af de tre JUnit 4 idiomer, men det er ikke altid det rigtige. Tabellen sammenligner dem pรฅ de to spรธrgsmรฅl, der afgรธr valget: kan du hรฆvde budskabet, og ved du hvilken linje der blev kastet?

Tilgang Hรฆvder budskabet? Fastgรธr kastelinjen? Bedste for
@Test(forventet = X.klasse) Ingen Nej โ€” enhver linje i metoden kan kaste Korte tests, hvor kun undtagelsestypen har betydning.
prรธv / mislykkes() / fangst Ja, inden for fangstblokken Ja โ€” kun det bevogtede opkald overvรฅges Test, der skal undersรธge meddelelsen eller รฅrsagen.
@Regel ForventetUndtagelse Ja, via expectMessage() Ingen Legacy-suiter er allerede bygget pรฅ regler.

fail()-idiomet, som introduktionen nรฆvner, ser sรฅdan ud. Hvis kaldet ikke udlรธser et udfald, kรธres fail(), og testen rapporterer den besked, du skrev:

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

ExpectedException-reglen ligger mellem de to. Den blev udfaset i JUnit 4.13 til fordel for assertThrows-metoden beskrevet nedenfor, sรฅ ny JUnit 4 tests bรธr ikke anvende det.

Sรฅdan tester du undtagelser i JUnit 5 med assertThrows()

JUnit 5 fjerner den forventede parameter helt fra @Test. Jupiter leverer assertThrows(), som tager exception-klassen og en lambda, der indeholder koden under test. Den returnerer den undtagelse, den fangede, sรฅ beskeden, รฅrsagen og ethvert brugerdefineret felt kan hรฆvdes bagefter.

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 relaterede pรฅstande rund familien af:

  • hรฆvderKast accepterer undtagelsestypen eller enhver underklasse af den.
  • hรฆvderKastPrรฆcis afviser en underklasse, sรฅ kun den navngivne type bestรฅr.
  • hรฆvderKasterIkke angiver den modsatte forventning, at blokken fuldfรธres rent.

JUnit 4-koden pรฅ denne side kรธrer stadig pรฅ JUnit Platform gennem den gamle motor, sรฅ intet ovenfor skal omskrives for at fortsรฆtte med at virke, mens et projekt migrerer.

Almindelige fejl ved test af undtagelser i JUnit

Undtagelsestests fejler pรฅ et lille antal genkendelige mรฅder. Hver rรฆkke angiver symptomet, รฅrsagen og lรธsningen.

Symptom ร…rsag Fix
Forventet undtagelse: java.lang.ArithmeticException Metoden blev gennemfรธrt uden at kaste. Kontroller, at inputtet virkelig er ugyldigt, og kรธr derefter igen.
Testen bestรฅr, men den forkerte linje blev kastet Den forventede parameter overvรฅger hele metoden, inklusive opsรฆtningen. Flyt opsรฆtningen ud, eller skift til assertThrows omkring รฉt kald.
Uhรฅndteret undtagelsestype i editoren En kontrolleret undtagelse udlรธses, men deklareres aldrig. Tilfรธj throws til testmetodesignaturen.
Testen bestรฅr en underklasse, du ikke havde til hensigt assertThrows accepterer underklasser af den navngivne type. Brug assertThrowsExactly til et strict typematch.
forventet er ikke en gyldig attribut Testen blev kompileret mod Jupiter @Test-annotationen. Importรฉr org.junit.Test for JUnit 4, eller flyt til assertThrows.

Den sidste rรฆkke er den, der fanger de fleste under migreringen, fordi begge annotationer hedder @Test, og kun importen adskiller dem.ping en JUnit version pr. test sag klasse undgรฅr hele klasseproblemet.

Ofte Stillede Spรธrgsmรฅl

Den forventede parameter kan ikke kontrollere en besked. Indpak kaldet i en try-blok, kald fail() umiddelbart efter den, og udfรธr en assert pรฅ getMessage() inde i catch-blokken. JUnit 5 gรธr dette enklere, fordi assertThrows returnerer den fangede undtagelse.

JUnit dumper testen og rapporterer "Forventet undtagelse" efterfulgt af den klasse, du har navngivet. Intet andet rapporteres, sรฅ en test, der aldrig kaster fejl, ser identisk ud med en, hvis produktionskode lydlรธst รฆndrede adfรฆrd.

AI-assistenter lรฆser en metode, oplister de input, der nรฅr hver throw-sรฆtning, og udarbejder en test pr. branch. Betragt outputtet som et udgangspunkt: assistenten udleder undtagelsestypen fra koden, sรฅ et forkert throw kopieres nรธjagtigt ind i testen.

CoPilot fรธlger den stil, der allerede findes i filen, sรฅ et blandet projekt fรฅr en blanding. Tjek importlinjen, fรธr du accepterer et forslag, fordi org.junit.Test og org.junit.jupiter.api.Test ser identiske ud i editoren.

Den findes stadig, men den blev udfaset i JUnit 4.13 og aldrig porteret til Jupiter. Eksisterende suiter kan beholde den; nye tests bรธr bruge assertThrows, som lรฆser bedre og ikke behรธver et offentligt regelfelt.

Ja. Lambda-parameteren er en eksekverbar fil, som er deklareret til at kaste en Throwable, sรฅ en kontrolleret undtagelse behรธver ingen throws-klausul pรฅ selve testmetoden. Det samme gรฆlder for JUnit 4 prรธv at fange idiom.

assertThrows accepterer enhver underklasse af den type, du navngiver, sรฅ forventning om RuntimeException sender ogsรฅ NullPointerException videre. Brug assertThrowsExactly, nรฅr den prรฆcise klasse er vigtig, eller navngiv den smalleste type, du rent faktisk forventer.

Kun hvor undtagelsen er en del af betingelsentract. Ved test af en undtagelse lover metoden aldrig at blokere utilsigtet adfรฆrd og gรธr refactoring vanskeligere, hvilket modbeviser testens pointe.

Opsummer dette indlรฆg med: