JUnit Test dell'eccezione prevista: @Test(previsto)

โšก Riepilogo intelligente

JUnit Il test delle eccezioni conferma che un metodo lancia l'errore che dovrebbe lanciare, utilizzando il parametro previsto opzionale dell'annotazione @Test in JUnit 4 e il metodo assertThrows in JUnit 5.

  • ๐Ÿ”˜ Scopo: Dimostra che un input non valido produce l'eccezione documentata anzichรฉ una risposta errata silenziosa.
  • โ˜‘๏ธ Sintassi: @Test(expected = ArithmeticException.class) supera la verifica solo quando viene generato esattamente quel tipo di eccezione.
  • โœ… Esempio: JUnitIl messaggio รจ diviso per zero e AirthematicTest si aspetta la conseguente ArithmeticException.
  • ๐Ÿงช Alternativa: Un blocco try seguito da fail() consente di esaminare l'eccezione intercettata prima di verificarla.
  • ๏ธ JUnit 5: assertThrows restituisce l'eccezione intercettata, quindi รจ possibile verificare sia il messaggio che la causa.
  • ???? Insidia: Il parametro previsto viene passato ovunque si verifichi l'eccezione, il che puรฒ nascondere un errore nel codice di configurazione.

JUnit Test di eccezione previsto utilizzando il parametro @Test(expected).

JUnit fornisce la possibilitร  di trace l'eccezione e anche per verificare se il codice sta generando l'eccezione prevista o meno.

JUnit 4 offre un modo semplice e leggibile per testare le eccezioni. Puoi usare:

  • Il parametro opzionale (previsto) del Annotazione @Teste
  • A trace le informazioni, รจ possibile utilizzare โ€œfail()โ€.

Mentre analisi un'eccezione, devi assicurarti che la classe di eccezione che stai fornendo in quel parametro opzionale del Annotazione @Test รจ la stessa che il metodo effettivamente lancia. Questo perchรฉ ti aspetti un'eccezione dal metodo che stai unit test; altrimenti il โ€‹โ€‹nostro JUnit il test fallirebbe.

Esempio: @Test(expected = IllegalArgumentException.class)

Utilizzando il parametro โ€œexpectedโ€, รจ possibile specificare il nome dellโ€™eccezione che il nostro test potrebbe generare. Nellโ€™esempio precedente, si utilizza โ€œIllegalArgumentException", che verrร  generata dal test se uno sviluppatore utilizza un argomento non consentito.

Esempio di utilizzo di @Test(expected)

Comprendiamo il test delle eccezioni creando un Java classe con un metodo che lancia un eccezioneLo gestirai e lo testerai in una classe di test. Considera JUnitIl file Message.java contiene un metodo che esegue un'operazione matematica. La divisione alla riga 14 divide per zero, quindi il metodo genera sempre un'eccezione "ArithmeticException". Vedi sotto:

JUnitClasse di messaggi in Eclipse con printMessage divisione per zero alla riga 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 Spiegazione:

  • Code Linea 7: Creazione di un costruttore parametrizzato con inizializzazione del campo.
  • Code Linea 11-14: Creazione di un metodo per l'operazione matematica.
  • Code Linea 18: Creazione di un altro metodo per stampare un messaggio.
  • Code Linea 20: Creazione di una nuova stringa per stampare un messaggio.
  • Code Linea 22: Stampa del nuovo messaggio creato alla riga 20.

Creiamo una classe di test per quanto sopra Java classe per verificare l'eccezione.

Di seguito รจ riportata la classe di test che esegue il test unitario dell'eccezione (ArithmeticException in questo caso) generata da quanto sopra. Java classe:

AirthematicTest.java

Lo screenshot qui sotto mostra lo stesso test nell'editor, dove il file รจ salvato come AirthematicTest1, con il parametro previsto evidenziato alla riga 13:

Classe AirthematicTest1 in Eclipse con @Test(expected = ArithmeticException.class) evidenziato alla riga 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 Spiegazione:

  • Code Linea 13: Utilizziamo l'annotazione @Test per creare il nostro test. Quando si esegue il metodo della classe sopra menzionata, verrร  richiamata un'operazione matematica. In questo caso รจ prevista un'eccezione ArithmeticException, quindi la si specifica come parametro in @Test.
  • Code Linea 17: Richiamando printMessage() da JUnitMessaggio.java.
  • Code Linea 21-22: Creazione di un altro metodo di test per verificare il messaggio "Ciao", questa volta senza un parametro previsto.

La classe contiene due metodi di test, quindi una singola esecuzione li esegue entrambi: quello che si aspetta un'eccezione ArithmeticException e quello che verifica la stringa restituita.

Nota: Questo esempio compare con tre nomi diversi nel materiale originale: il listato chiama la classe AirthematicTest, lo screenshot dell'editor mostra AirthematicTest1 e la visualizzazione dei risultati riporta JunitTestExample. Il codice รจ identico in tutti i casi; cambia solo il nome del file.

Eseguiamolo e verifichiamo il risultato. Il JUnit la vista sottostante riporta l'esecuzione di Esempio di test Junit.java.

Produzione:

Ecco l'output, che mostra un test riuscito senza errori. trace come indicato di seguito:

Eclipse JUnit Visualizza il report Esecuzioni 2/2 con zero errori e zero fallimenti per JunitTestExample

Entrambi i metodi sono verdi. Il primo passa perchรฉ l'ArithmeticException dichiarata รจ effettivamente arrivata, e il secondo passa perchรฉ la stringa restituita corrispondeva. Se la divisione non avesse mai generato, JUnit Il primo metodo avrebbe fallito con il messaggio "Eccezione prevista: java.lang.ArithmeticException".

Tre modi per testare un'eccezione in JUnit 4

Il parametro atteso รจ il piรน breve dei tre JUnit 4 espressioni idiomatiche, ma non sempre รจ quella giusta. La tabella le confronta in base a due domande che ne determinano la scelta: puoi affermare il messaggio e sai quale frase รจ stata pronunciata?

Approccio Afferma il messaggio? Fissa la linea di lancio? migliori per
@Test(expected = X.class) Non No, qualsiasi riga del metodo puรฒ generare un errore Test brevi in โ€‹โ€‹cui conta solo il tipo di eccezione.
prova / fallisci() / cattura Sรฌ, all'interno del blocco di sicurezza Sรฌ, viene monitorata solo la chiamata controllata. Test che devono esaminare il messaggio o la causa.
@Regola ExpectedException Sรฌ, tramite expectMessage() Non Suite legacy giร  basate su regole.

L'idioma fail() menzionato nell'introduzione si presenta in questo modo. Se la chiamata non genera un'eccezione, viene eseguito fail() e il test riporta il messaggio che hai scritto:

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

La regola ExpectedException si trova tra le due. รˆ stata deprecata in JUnit 4.13 a favore del metodo assertThrows descritto di seguito, quindi nuovo JUnit 4 test non dovrebbero adottarlo.

Come testare le eccezioni in JUnit 5 con assertThrows()

JUnit 5 rimuove completamente il parametro previsto da @Test. Jupiter fornisce assertThrows(), che accetta la classe dell'eccezione e una lambda contenente il codice da testare. Restituisce l'eccezione intercettata, in modo che il messaggio, la causa e qualsiasi campo personalizzato possano essere verificati in seguito.

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 correlati asserzioni completa la famiglia:

  • assertThrows accetta il tipo di eccezione o qualsiasi sua sottoclasse.
  • assertThrowsExactly rifiuta una sottoclasse, quindi passa solo il tipo denominato.
  • assertDoesNotThrow afferma l'aspettativa opposta, ovvero che il blocco venga completato senza intoppi.

Migliori JUnit 4 Il codice su questa pagina รจ ancora in esecuzione JUnit La piattaforma utilizza il motore vintage, quindi nulla di quanto sopra deve essere riscritto per continuare a funzionare durante la migrazione di un progetto.

Errori comuni durante il test delle eccezioni in JUnit

I test di eccezione falliscono in un numero limitato di modi riconoscibili. Ogni riga indica il sintomo, la causa e la soluzione.

Sintomo Causare Fissare
Eccezione prevista: java.lang.ArithmeticException Il metodo รจ stato completato senza lanciare. Verifica che l'input sia effettivamente non valido, quindi esegui nuovamente il comando.
Il test passa ma la linea sbagliata รจ stata lanciata Il parametro previsto monitora l'intero metodo, inclusa la fase di configurazione. Sposta la configurazione all'esterno oppure passa ad assertThrows intorno a una chiamata.
Tipo di eccezione non gestita nell'editor Viene generata un'eccezione controllata, ma questa non viene mai dichiarata. Aggiungi throws alla firma del metodo di test.
I test superano una sottoclasse che non avevi previsto assertThrows accetta sottoclassi del tipo specificato. Utilizzare assertThrowsExactly per una corrispondenza di tipo rigorosa.
"expected" non รจ un attributo valido Il test รจ stato compilato utilizzando l'annotazione @Test di Jupiter. Importa org.junit.Test per JUnit 4, oppure passare ad assertThrows.

L'ultima riga รจ quella che mette in difficoltร  la maggior parte delle persone durante la migrazione, perchรฉ entrambe le annotazioni si chiamano @Test e solo l'importazione le distingue. Keeping prima JUnit versione per caso di prova la classe evita l'intera classe di problemi.

DOMANDE FREQUENTI

Il parametro previsto non puรฒ controllare un messaggio. Racchiudi la chiamata in un blocco try, chiama fail() immediatamente dopo e verifica getMessage() all'interno del blocco catch. JUnit 5 semplifica la cosa perchรฉ assertThrows restituisce l'eccezione intercettata.

JUnit Il test fallisce e viene segnalato "Eccezione prevista" seguito dalla classe specificata. Non viene segnalato nient'altro, quindi un test che non genera mai eccezioni appare identico a uno il cui codice di produzione ha modificato silenziosamente il proprio comportamento.

Gli assistenti IA leggono un metodo, elencano gli input che raggiungono ogni istruzione throw e creano un test per ogni ramo. Considera l'output come punto di partenza: l'assistente deduce il tipo di eccezione dal codice, quindi un'eccezione throw errata viene copiata fedelmente nel test.

Secondo pilota segue lo stile giร  presente nel file, quindi un progetto misto otterrร  uno stile misto. Controlla la riga di importazione prima di accettare un suggerimento, perchรฉ org.junit.Test e org.junit.jupiter.api.Test appaiono identici nell'editor.

Esiste ancora, ma รจ stato deprecato nel JUnit 4.13 e mai portato su Jupiter. Le suite esistenti possono mantenerlo; i nuovi test dovrebbero usare assertThrows, che รจ piรน leggibile e non necessita di un campo di regole pubblico.

Sรฌ. Il parametro lambda รจ un Executable, che รจ dichiarato per lanciare Throwable, quindi un'eccezione controllata non necessita di una clausola throws sul metodo di test stesso. Lo stesso vale per il JUnit 4. Prova e cogli l'idioma.

`assertThrows` accetta qualsiasi sottoclasse del tipo specificato, quindi l'aspettativa di `RuntimeException` passa automaticamente anche in caso di `NullPointerException`. Utilizzare `assertThrowsExactly` quando รจ importante specificare la classe esatta oppure indicare il tipo piรน specifico che ci si aspetta.

Solo quando l'eccezione fa parte del contract. Testare un'eccezione con il metodo non garantisce mai di generare blocchi in caso di comportamenti accidentali e rende piรน difficile il refactoring, vanificando lo scopo del test.

Riassumi questo post con: