unitarias unitaria tutorial sintaxis pruebas prueba fail ejemplos configuracion con java unit-testing testing junit

java - unitaria - sintaxis junit



¿Mala forma para que la prueba JUnit arroje una excepción? (8)

Desde JUnit 4.7 tiene la posibilidad de usar una regla ExpectedException y debería usarla. La regla le da la posibilidad de definir exactamente el método llamado donde debe arrojarse la excepción en su código de prueba. Además, puede hacer coincidir fácilmente una cadena con el mensaje de error de la excepción. En tu caso, el código es así:

@Rule public ExpectedException expectedException = ExpectedException.none(); @Test public void test() { //working code here... expectedException.expect(InvalidIPAddressException.class); IPAddress addr = new IPAddress(null); }

ACTUALIZACIÓN: en su libro Pruebas de unidades prácticas con JUnit y Mockito Tomek Kaczanowski argumenta en contra del uso de ExpectedException, porque la regla "rompe el flujo de arreglos / actos / afirmaciones" de una prueba unitaria (sugiere utilizar la excepción de captura) Biblioteca en su lugar). Aunque puedo entender su argumento, creo que usar la regla está bien si no quieres introducir otra biblioteca de terceros (usar la regla es mejor que capturar la excepción "manualmente" de todos modos).

Soy bastante nuevo en JUnit, y realmente no sé cuáles son las mejores prácticas para las excepciones y el manejo de excepciones.

Por ejemplo, digamos que estoy escribiendo pruebas para una clase IPAddress. Tiene un constructor IPAddress (String addr) que arrojará una InvalidIPAddressException si addr es nulo. Por lo que puedo decir al buscar en Google, la prueba para el parámetro nulo se verá así.

@Test public void testNullParameter() { try { IPAddress addr = new IPAddress(null); assertTrue(addr.getOctets() == null); } catch(InvalidIPAddressException e) { return; } fail("InvalidIPAddressException not thrown."); }

En este caso, try / catch tiene sentido porque sé que se aproxima la excepción.

Pero ahora si quiero escribir testValidIPAddress (), hay un par de maneras de hacerlo:

Camino # 1:

@Test public void testValidIPAddress() throws InvalidIPAddressException { IPAddress addr = new IPAddress("127.0.0.1"); byte[] octets = addr.getOctets(); assertTrue(octets[0] == 127); assertTrue(octets[1] == 0); assertTrue(octets[2] == 0); assertTrue(octets[3] == 1); }

Camino # 2:

@Test public void testValidIPAddress() { try { IPAddress addr = new IPAddress("127.0.0.1"); byte[] octets = addr.getOctets(); assertTrue(octets[0] == 127); assertTrue(octets[1] == 0); assertTrue(octets[2] == 0); assertTrue(octets[3] == 1); } catch (InvalidIPAddressException e) { fail("InvalidIPAddressException: " + e.getMessage()); } }

¿Es una práctica estándar lanzar excepciones inesperadas a JUnit o simplemente tratar con ellas?

Gracias por la ayuda.


En general, el # 1 es el camino a seguir, no hay ninguna razón para invocar un error por error, ya sea que la prueba haya fallado.

El único momento en que # 2 tiene sentido si necesita un buen mensaje de lo que salió mal, y solo una excepción no se lo dará a usted. Entonces capturar y fallar puede tener sentido para anunciar mejor el motivo del fracaso.


En realidad, el viejo estilo de las pruebas de excepción es envolver un bloque try alrededor del código que arroja la excepción y luego agregar una instrucción fail() al final del bloque try. Algo como esto:

public void testNullParameter() { try { IPAddress addr = new IPAddress(null); fail("InvalidIPAddressException not thrown."); } catch(InvalidIPAddressException e) { assertNotNull(e.getMessage()); } }

Esto no es muy diferente de lo que escribiste, pero:

  1. Su assertTrue(addr.getOctets() == null); es inútil
  2. La intención y la sintaxis son más claras de IMO y, por lo tanto, más fáciles de leer.

Aún así, esto es un poco feo. Pero aquí es donde JUnit 4 viene al rescate, ya que las pruebas de excepción son una de las mayores mejoras en JUnit 4. Con JUnit 4, ahora puede escribir su prueba de esta manera:

@Test (expected=InvalidIPAddressException.class) public void testNullParameter() throws InvalidIPAddressException { IPAddress addr = new IPAddress(null); }

Bien, ¿verdad?

Ahora, con respecto a la verdadera pregunta, si no espero lanzar una excepción, definitivamente iré por el camino # 1 (porque es menos detallado) y dejaré que JUnit maneje la excepción y falle la prueba como se esperaba.


OMI es mejor manejar la excepción y mostrar los mensajes apropiados de la prueba que arrojarla de una prueba.


Para la prueba nula, simplemente puede hacer esto:

public void testNullParameter() { try { IPAddress addr = new IPAddress(null); fail("InvalidIPAddressException not thrown."); } catch(InvalidIPAddressException e) { } }

Si la excepción tiene un mensaje, también puede verificar ese mensaje en la captura si lo desea. P.ej

String actual = e.getMessage(); assertEquals("Null is not a valid IP Address", actual);

Para la prueba válida no es necesario detectar la excepción. Una prueba fallará automáticamente si se lanza una excepción y no se detecta. Así que el camino # 1 sería todo lo que necesita, ya que fallará y el seguimiento de la pila estará disponible para usted de todos modos para su placer visual.


Para las pruebas donde no espero una excepción, no me molesto en atraparla. Dejo que JUnit capte la excepción (lo hace de manera confiable) y no la atiendo en absoluto más allá de declarar la causa de los throws (si es necesario).

Veo re. su primer ejemplo de que no está haciendo uso de la anotación @expected .

@Test (expected=IndexOutOfBoundsException.class) public void elementAt() { int[] intArray = new int[10]; int i = intArray[20]; // Should throw IndexOutOfBoundsException }

Lo uso para todas las pruebas que estoy probando para arrojar excepciones. Es más breve que el patrón de captura / falla equivalente que tuve que usar con Junit3.


Reg: prueba de excepciones
Estoy de acuerdo con "Pascal Thivent", es decir, uso @Test (expected=InvalidIPAddressException.class)

Reg: Pruebas para testValidIPAddress

IPAddress addr = new IPAddress("127.0.0.1"); byte[] octets = addr.getOctets();

Escribiría una prueba como

class IPAddressTests { [Test] public void getOctets_ForAValidIPAddress_ShouldReturnCorrectOctect() { // Test code here } }

El punto es cuando testinput es VÁLIDO ipAddress
La prueba debe ser sobre los métodos / capacidades públicas en la clase, afirmando que están funcionando como excepciones


Si entiendo su pregunta, la respuesta es: preferencia personal.

personalmente tiro mis excepciones en las pruebas. en mi opinión, una prueba que falla por aserción es equivalente a una prueba que falla por una excepción no detectada. ambos muestran algo que necesita ser arreglado.

lo importante para recordar en las pruebas es la cobertura del código.