JUnit Prueba de excepción esperada: @Test (esperada)

⚡ Resumen inteligente

JUnit Las pruebas de excepciones confirman que un método lanza el error que se supone que debe lanzar, utilizando el parámetro opcional esperado de la anotación @Test en JUnit 4 y el método assertThrows en JUnit 5.

  • 🔘 Propósito: Demuestra que una entrada no válida produce la excepción documentada en lugar de una respuesta incorrecta silenciosa.
  • ☑️ Sintaxis: @Test(expected = ArithmeticException.class) pasa solo cuando se lanza ese tipo exacto de excepción.
  • ✅ Ejemplo: JUnitEl mensaje se divide por cero y AirthematicTest espera la excepción ArithmeticException resultante.
  • 🧪 alternativa: Un bloque try seguido de fail() te permite inspeccionar la excepción capturada antes de realizar una aserción sobre ella.
  • 🛠️ JUnit 5: assertThrows devuelve la excepción capturada, por lo que también se pueden afirmar el mensaje y la causa.
  • 📌 Trampa: El parámetro esperado se pasa independientemente de dónde se produzca la excepción, lo que puede ocultar un fallo en el código de configuración.

JUnit Prueba de excepción esperada utilizando el parámetro @Test(expected)

JUnit proporciona la facilidad para tracy la excepción y también para comprobar si el código está generando la excepción esperada o no.

JUnit 4 proporciona una forma sencilla y legible de realizar pruebas de excepciones. Puede utilizar:

  • El parámetro opcional (esperado) del Anotación @Test, y
  • A tracy la información, se puede utilizar “fail()”.

Aunque las pruebas una excepción, debe asegurarse de que la clase de excepción que está proporcionando en ese parámetro opcional de la Anotación @Test es la misma que realmente lanza el método. Esto se debe a que esperas una excepción del método que estás examen de la unidad; de lo contrario nuestro JUnit la prueba fallaría.

Ejemplo: @Test(expected = IllegalArgumentException.class)

Al usar el parámetro “expected”, puede especificar el nombre de la excepción que nuestra prueba puede generar. En el ejemplo anterior, está usando “Argumento de excepción ilegal", que será lanzada por la prueba si un desarrollador utiliza un argumento que no está permitido.

Ejemplo usando @Test(expected)

Entendamos las pruebas de excepciones creando una Java clase con un método que lanza una excepción excepción. Lo manejarás y lo probarás en una clase de prueba. Considera JUnitEl archivo Message.java contiene un método que realiza una operación matemática. La división en la línea 14 divide por cero, por lo que el método siempre lanza una excepción "ArithmeticException". Véase a continuación:

JUnitClase Mensaje en Eclipse con printMessage dividiendo por cero en la línea 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 Explicación:

  • Code Línea 7: Creando un constructor parametrizado con inicialización de campo.
  • Code Línea 11-14: Crear un método para la operación matemática.
  • Code Línea 18: Creando otro método para imprimir un mensaje.
  • Code Línea 20: Creando una nueva cadena para imprimir un mensaje.
  • Code Línea 22: Imprimiendo el nuevo mensaje creado en la línea 20.

Vamos a crear una clase de prueba para lo anterior. Java clase para verificar la excepción.

A continuación se muestra la clase de prueba que realiza pruebas unitarias de la excepción (ArithmeticException en este caso) lanzada desde lo anterior. Java clase:

AirthematicTest.java

La captura de pantalla que aparece a continuación muestra la misma prueba en el editor, donde el archivo se guarda como AirthematicTest1, con el parámetro esperado resaltado en la línea 13:

Clase AirthematicTest1 en Eclipse con @Test(expected = ArithmeticException.class) resaltado en la línea 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 Explicación:

  • Code Línea 13: Utilizamos la anotación @Test para crear nuestra prueba. Al ejecutar el método de la clase anterior, se invocará una operación matemática. En este caso, se espera una excepción ArithmeticException, por lo que la incluimos como parámetro en @Test.
  • Code Línea 17: Invocando printMessage() desde JUnitMensaje.java.
  • Code Línea 21-22: Creando otro método de prueba para verificar el mensaje "Hola", esta vez sin un parámetro esperado.

La clase contiene dos métodos de prueba, por lo que una sola ejecución ejecuta ambos: el que espera una ArithmeticException y el que realiza una comprobación sobre la cadena devuelta.

Nota: Este ejemplo aparece con tres nombres diferentes en el material original: en la lista se llama a la clase AirthematicTest, en la captura de pantalla del editor se muestra AirthematicTest1 y en la vista de resultados se indica JunitTestExample. El código es idéntico en todos los casos; solo difiere el nombre del archivo.

Vamos a ejecutarlo y verificar el resultado. El JUnit Ver a continuación informa sobre la carrera de Ejemplo de prueba Junit.java.

Salida:

Aquí está el resultado, que muestra una prueba exitosa sin fallos. trace como se indica a continuación:

Eclipse JUnit Ver informes. Ejecuciones 2/2 con cero errores y cero fallos para JunitTestExample.

Ambos métodos son verdes. El primero pasa porque la ArithmeticException que declaró sí llegó, y el segundo pasa porque la cadena devuelta coincidió. Si la división nunca se hubiera lanzado, JUnit El primer método habría fallado con el mensaje “Excepción esperada: java.lang.ArithmeticException”.

Tres maneras de probar una excepción en JUnit 4

El parámetro esperado es el más corto de los tres. JUnit 4 modismos, pero no siempre es el correcto. La tabla los compara en función de las dos preguntas que deciden la elección: ¿puedes afirmar sobre el mensaje? y ¿sabes qué línea lanzó?

Nuevo enfoque ¿Afirma el mensaje? ¿Fija la línea de lanzamiento? Mejores para
@Test(expected = X.class) No No, cualquier línea en el método puede generar un error. Pruebas cortas donde solo importa el tipo de excepción.
intentar / fallar() / capturar Sí, dentro del bloque de recepción Sí, solo se vigila la llamada de vigilancia. Pruebas que deben examinar el mensaje o la causa.
@Regla ExpectedException Sí, a través de expectMessage() No Los paquetes heredados ya se basan en reglas.

La función fail() que se menciona en la introducción tiene este aspecto. Si la llamada no genera una excepción, fail() se ejecuta y la prueba informa del mensaje que escribiste:

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

La regla ExpectedException se sitúa entre las dos. Fue descontinuada en JUnit 4.13 a favor del método assertThrows que se describe a continuación, por lo que es nuevo JUnit 4 pruebas no deberían adoptarlo.

Cómo probar excepciones en JUnit 5 con assertThrows()

JUnit 5 elimina por completo el parámetro esperado de @Test. Jupiter proporciona asertThrows (), que recibe la clase de excepción y una función lambda que contiene el código que se está probando. Devuelve la excepción que capturó, de modo que el mensaje, la causa y cualquier campo personalizado se pueden verificar posteriormente.

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());
    }
}

Tres relacionados afirmaciones Completar la familia:

  • assertThrows acepta el tipo de excepción o cualquier subclase del mismo.
  • assertThrowsExactamente Rechaza una subclase, por lo que solo pasa el tipo nombrado.
  • assertDoesNotThrow Se afirma la expectativa opuesta, que el bloque se complete sin problemas.

El JUnit 4 códigos en esta página todavía se ejecutan en el JUnit La plataforma funciona mediante el motor clásico, por lo que no es necesario reescribir nada de lo anterior para que siga funcionando mientras un proyecto migra.

Errores comunes al probar excepciones en JUnit

Las pruebas de excepciones fallan de maneras fácilmente reconocibles. Cada fila indica el síntoma, la causa y la solución.

Síntoma Causa Solución
Excepción esperada: java.lang.ArithmeticException El método se completó sin lanzar. Comprueba que la entrada sea realmente inválida y vuelve a ejecutar el programa.
La prueba pasa pero se lanzó la línea incorrecta El parámetro esperado supervisa todo el método, incluida la configuración. Mueva la configuración a otro lugar o cambie a assertThrows alrededor de una llamada.
Tipo de excepción no controlada en el editor Se lanza una excepción controlada, pero nunca se declara. Agregue excepciones a la firma del método de prueba.
La prueba se ejecuta en una subclase que no pretendías. assertThrows acepta subclases del tipo especificado. Utilice assertThrowsExactly para una coincidencia de tipo estricta.
esperado no es un atributo válido La prueba se compiló utilizando la anotación Jupiter @Test. Importar org.junit.Test para JUnit 4, o pasar a assertThrows.

La última fila es la que suele confundir a la mayoría de la gente durante la migración, porque ambas anotaciones se llaman @Test y solo la importación las distingue. Keeping uno JUnit versión por caso de prueba Esta clase evita todo el problema.

Preguntas Frecuentes

El parámetro esperado no puede verificar un mensaje. Envuelva la llamada en un bloque try, llame a fail() inmediatamente después y realice una aserción en getMessage() dentro del bloque catch. JUnit La opción 5 simplifica esto porque assertThrows devuelve la excepción capturada.

JUnit La prueba falla y se informa de una "Excepción esperada" seguida de la clase que especificaste. No se informa de nada más, por lo que una prueba que nunca genera una excepción parece idéntica a una cuyo código de producción cambió su comportamiento silenciosamente.

Los asistentes de IA leen un método, enumeran las entradas que llegan a cada instrucción throw y elaboran una prueba para cada rama. Considere la salida como un punto de partida: el asistente infiere el tipo de excepción a partir del código, por lo que una excepción throw incorrecta se copia fielmente en la prueba.

Copilot Sigue el estilo que ya existe en el archivo, por lo que un proyecto mixto obtiene una mezcla. Revisa la línea de importación antes de aceptar una sugerencia, ya que org.junit.Test y org.junit.jupiter.api.Test se ven idénticos en el editor.

Todavía existe, pero fue descontinuado en JUnit 4.13 y nunca se adaptó a Jupiter. Las suites existentes pueden conservarlo; las nuevas pruebas deberían usar assertThrows, que es más legible y no necesita un campo de regla público.

Sí. El parámetro lambda es un ejecutable, que está declarado para lanzar Throwable, por lo que una excepción verificada no necesita una cláusula throws en el propio método de prueba. Lo mismo es cierto para el JUnit 4. Modismo de intentar atrapar.

assertThrows acepta cualquier subclase del tipo que especifique, por lo que esperar RuntimeException también permite NullPointerException. Use assertThrowsExactly cuando la clase exacta sea importante, o especifique el tipo más específico que realmente espera.

Solo cuando la excepción forma parte de la condicióntract. Probar una excepción: el método nunca promete lanzar bloqueos en un comportamiento accidental y dificulta la refactorización, lo que anula el propósito de la prueba.

Resumir este post con: