2009-09-11 41 views
19

¿Es posible probar múltiples excepciones en una única prueba de unidad JUnit? Sé con una sola excepción se puede utilizar, por ejemploPrueba de excepciones múltiples con anotaciones JUnit 4

@Test(expected=IllegalStateException.class) 

Ahora, si quiero probar otra excepción (por ejemplo, NullPointerException), se puede hacer esto en la misma anotación, una anotación diferente o me ¿Necesitas escribir otra prueba unitaria por completo?

+1

Si más de una excepción indica que el código probado funciona como se esperaba, entonces la prueba no está bien definida. Deberías esperar exactamente una cosa de una prueba. – Buhb

Respuesta

18

Usted realmente quiere que la prueba haga una cosa, y para probar eso. Si no está seguro de qué excepción se lanzará, eso no me parece una buena prueba.

p. Ej. (En pseudo-código)

try { 
    badOperation(); 
    /// looks like we succeeded. Not good! Fail the test 
} 
catch (ExpectedException e) { 
    // that's fine 
} 
catch (UnexpectedException e) { 
    // that's NOT fine. Fail the test 
} 

por lo que si desea probar que su método lanza 2 excepciones diferentes (para 2 juegos de entradas), entonces usted tendrá 2 pruebas.

+0

Normalmente llamo a fail() dentro del bloque try, inmediatamente después de badOperation(). – Yuval

+0

En cualquier punto dado, estoy seguro de qué declaración espero arrojar un error. En una prueba, deseo probar que se arrojan todas las excepciones esperadas. Seré sincero, no estoy muy contento con la forma de anotar las excepciones: una mala prueba puede causar una excepción esperada en un punto inesperado de la prueba. En ese sentido, prefiero el try-catch-fail de probar una excepción, pero se ve feo. Sin embargo, supongo que tienes razón en cierto sentido: mis pruebas deberían ser más atómicas (en lugar de probar todo por un método en una prueba de unidad única, como estoy tratando de hacer). –

+0

@Yuval - Estaba tratando de ser agnóstico de framework de prueba en lo anterior. Sin embargo, he enmendado para ser más claro. –

0

¿Cómo esperas que "esperado" s funcione? Un método solo puede arrojar una excepción.

Debería escribir una prueba de unidad diferente para cada forma en que el método puede fallar. Entonces, si el método arroja legítimamente dos excepciones, entonces necesita dos pruebas configuradas para forzar el método de lanzar cada excepción.

+0

Un método solo puede arrojar una excepción, pero puede declararse como arrojando muchas excepciones diferentes. Diga que un método puede arrojar 4 tipos de excepciones, lanzando A o B pasa la prueba, tirando C o D falla la prueba. Esto sería una herramienta fácil de 'esperar' una matriz de clases en lugar de una sola clase – Glen

+2

Pero bajo un conjunto de datos solo puede fallar de una manera. –

0

mantén las pruebas lo más simples y cortas posible. la intención de un JUnit-Test es probar solo una funcionalidad simple o una sola forma de falla.

De hecho, para estar seguro, debe crear al menos una prueba para cada forma de ejecución posible.

Normalmente, esto no siempre es posible porque si tiene un método que analiza una cadena, hay tantas posibles combinaciones de cadenas que no puede abarcar todo.

mantenerlo corto y simple.

puede tener 30-40 métodos de prueba para un solo método fácilmente ... ¿realmente importa?

respecto

10

Esto no es posible con la anotación.

Con JUnit 4.7 puede utilizar la nueva regla ExpectedException

public static class HasExpectedException { 
    @Interceptor 
    public ExpectedException thrown= new ExpectedException(); 

    @Test 
    public void throwsNothing() { 
    } 

    @Test 
    public void throwsNullPointerException() { 
     thrown.expect(NullPointerException.class); 
     throw new NullPointerException(); 
    } 

    @Test 
    public void throwsNullPointerExceptionWithMessage() { 
     thrown.expect(NullPointerException.class); 
     thrown.expectMessage("happened?"); 
     throw new NullPointerException("What happened?"); 
    } 
} 

Más Ver


Si se está actualizando a JUnit 4.7 no es posible para usted, usted tiene que escribir una prueba unitaria desnuda de forma

public test() { 
    try { 
     methodCall(); // should throw Exception 
     fail(); 
    } 
    catch (Exception ex) { 
     assert((ex instanceof A) || (ex instanceof B) || ...etc...); 
     ... 
    } 

}

+0

Tuve un caso en el que tuve que probar para una de una lista de clases de excepción. Si usa una anotación @Nonnull en su código, una ejecución de prueba unitaria desde el IDE puede arrojar una InvalidArgumentException, pero si ejecuta la prueba desde una compilación (es decir, maven, gradle), aún debe probar null y podría responder con otro tipo de excepción El siguiente captura ambos casos: 'expected.expect (CoreMatchers.anyOf (CoreMatchers.instanceOf (IllegalArgumentException.class), CoreMatchers.instanceOf (MyCustomInvalidFieldValueException.class)));' –

2

Uso catch-exception:

// test 
public void testDo() { 

    // obj.do(1) must throw either A or B 
    catchException(obj).do(1); 
    assert caughtException() instanceof A 
     || caughtException() instanceof B; 

    // obj.do(2) must throw A but not SubclassOfA 
    catchException(obj).do(2); 
    assert caughtException() instanceof A 
     && !(caughtException() instanceof SubclassOfA); 

} 
-1
@Test(expected=Exception.class) 

la que se lanza todos expectativas

2

Aunque esto no es posible con JUnit 4, es es posible si cambia a TestNG, que le permite escribir

@Test(expectedExceptions = {IllegalArgumentException.class, NullPointerException.class}) 
+0

Gracias, esto funciona perfectamente bien :) – ABcDexter

Cuestiones relacionadas