utiliza unitarias unitaria pruebas prueba framework fail ejercicios con como java exception junit junit4 assert

java - unitarias - ¿Cómo afirma que se arroja una cierta excepción en las pruebas de JUnit 4?



pruebas junit en java (30)

¿Cómo puedo usar JUnit4 de forma idiomática para probar que algún código produce una excepción?

Aunque ciertamente puedo hacer algo como esto:

@Test public void testFooThrowsIndexOutOfBoundsException() { boolean thrown = false; try { foo.doStuff(); } catch (IndexOutOfBoundsException e) { thrown = true; } assertTrue(thrown); }

Recuerdo que hay una anotación o un Assert.xyz o algo que es mucho menos torpe y mucho más en el espíritu de JUnit para este tipo de situaciones.


Solución de Java 8

Si desea una solución que:

  • Utiliza Java 8 lambdas
  • No depende de ninguna magia JUnit.
  • Le permite verificar múltiples excepciones dentro de un solo método de prueba
  • Comprueba si una excepción es lanzada por un conjunto específico de líneas dentro de su método de prueba en lugar de cualquier línea desconocida en todo el método de prueba
  • Produce el objeto de excepción real que se lanzó para que pueda examinarlo más a fondo

Aquí hay una función de utilidad que escribí:

public final <T extends Throwable> T expectException( Class<T> exceptionClass, Runnable runnable ) { try { runnable.run(); } catch( Throwable throwable ) { if( throwable instanceof AssertionError && throwable.getCause() != null ) throwable = throwable.getCause(); //allows "assert x != null : new IllegalArgumentException();" assert exceptionClass.isInstance( throwable ) : throwable; //exception of the wrong kind was thrown. assert throwable.getClass() == exceptionClass : throwable; //exception thrown was a subclass, but not the exact class, expected. @SuppressWarnings( "unchecked" ) T result = (T)throwable; return result; } assert false; //expected exception was not thrown. return null; //to keep the compiler happy. }

( tomado de mi blog )

Úsalo de la siguiente manera:

@Test public void testThrows() { RuntimeException e = expectException( RuntimeException.class, () -> { throw new RuntimeException( "fail!" ); } ); assert e.getMessage().equals( "fail!" ); }


Solución JUnit 5

@Test void testFooThrowsIndexOutOfBoundsException() { Throwable exception = expectThrows( IndexOutOfBoundsException.class, foo::doStuff ); assertEquals( "some message", exception.getMessage() ); }

Más información sobre JUnit 5 en improved



¿Qué tal esto? Capte una excepción muy general, asegúrese de que salga del bloque catch, luego afirme que la clase de la excepción es lo que espera que sea. Esta afirmación fallará si a) la excepción es del tipo incorrecto (por ejemplo, si en su lugar obtuvo un puntero nulo) yb) la excepción nunca se lanzó.

public void testFooThrowsIndexOutOfBoundsException() { Throwable e = null; try { foo.doStuff(); } catch (Throwable ex) { e = ex; } assertTrue(e instanceof IndexOutOfBoundsException); }


Ahora que se lanzó JUnit 5, la mejor opción es usar Assertions.assertThrows() (consulte la Guía del usuario de Junit 5 ).

Aquí hay un ejemplo que verifica que se lanza una excepción, y usa Truth para hacer afirmaciones en el mensaje de excepción:

public class FooTest { @Test public void doStuffThrowsIndexOutOfBoundsException() { Foo foo = new Foo(); IndexOutOfBoundsException e = assertThrows( IndexOutOfBoundsException.class, foo::doStuff); assertThat(e).hasMessageThat().contains("woops!"); } }

Las ventajas sobre los enfoques en las otras respuestas son:

  1. Incorporado en JUnit
  2. Recibirá un mensaje de excepción útil si el código en la lambda no lanza una excepción, y un stacktrace si lanza una excepción diferente
  3. Conciso
  4. Permite que tus pruebas sigan Arrange-Act-Assert
  5. Puede indicar con precisión qué código espera lanzar la excepción.
  6. No es necesario que incluya la excepción esperada en la cláusula de throws
  7. Puede utilizar el marco de aserción de su elección para hacer afirmaciones sobre la excepción detectada

Se agregará un método similar a org.junit Assert en JUnit 4.13.


Como se contestó antes, hay muchas maneras de lidiar con las excepciones en JUnit. Pero con Java 8 hay otro: usando Lambda Expressions. Con Lambda Expressions podemos lograr una sintaxis como esta:

@Test public void verifiesTypeAndMessage() { assertThrown(new DummyService()::someMethod) .isInstanceOf(RuntimeException.class) .hasMessage("Runtime exception occurred") .hasMessageStartingWith("Runtime") .hasMessageEndingWith("occurred") .hasMessageContaining("exception") .hasNoCause(); }

assertThrown acepta una interfaz funcional, cuyas instancias se pueden crear con expresiones lambda, referencias de métodos o referencias de constructores. assertThrown acepta la interfaz y estará listo para manejar una excepción.

Esta es una técnica relativamente simple pero poderosa.

Eche un vistazo a esta publicación del blog que describe esta técnica: http://blog.codeleak.pl/2014/07/junit-testing-exception-with-java-8-and-lambda-expressions.html

El código fuente se puede encontrar aquí: https://github.com/kolorobot/unit-testing-demo/tree/master/src/test/java/com/github/kolorobot/exceptions/java8

Divulgación: Soy el autor del blog y del proyecto.


En Junit, hay cuatro maneras de probar la excepción.

  • para junit4.x, use el atributo ''esperado'' opcional de la anonación de prueba

    @Test(expected = IndexOutOfBoundsException.class) public void testFooThrowsIndexOutOfBoundsException() { foo.doStuff(); }

  • para junit4.x, use la regla ExpectedException

    public class XxxTest { @Rule public ExpectedException thrown = ExpectedException.none(); @Test public void testFooThrowsIndexOutOfBoundsException() { thrown.expect(IndexOutOfBoundsException.class) //you can test the exception message like thrown.expectMessage("expected messages"); foo.doStuff(); } }

  • También puede utilizar la forma clásica de prueba / captura ampliamente utilizada en el marco de Junit 3

    @Test public void testFooThrowsIndexOutOfBoundsException() { try { foo.doStuff(); fail("expected exception was not occured."); } catch(IndexOutOfBoundsException e) { //if execution reaches here, //it indicates this exception was occured. //so we need not handle it. } }

  • finalmente, para junit5.x, también puede usar assertThrows como sigue

    @Test public void testFooThrowsIndexOutOfBoundsException() { Throwable exception = assertThrows(IndexOutOfBoundsException.class, () -> foo.doStuff()); assertEquals("expected messages", exception.getMessage()); }

  • asi que

    • la primera forma se usa cuando solo desea probar el tipo de excepción
    • las otras tres formas se utilizan cuando desea un mensaje de excepción de prueba adicional
    • Si usas Junit 3, entonces se prefiere el tercero.
    • Si te gusta Junit 5, entonces te gustaría el 4to.
  • para obtener más información, puede leer github.com/junit-team/junit/wiki/Exception-testing y la guía del usuario de junit5 para obtener más información.


En mi humilde opinión, la mejor manera de verificar las excepciones en JUnit es el patrón try / catch / fail / assert:

// this try block should be as small as possible, // as you want to make sure you only catch exceptions from your code try { sut.doThing(); fail(); // fail if this does not throw any exception } catch(MyException e) { // only catch the exception you expect, // otherwise you may catch an exception for a dependency unexpectedly // a strong assertion on the message, // in case the exception comes from anywhere an unexpected line of code, // especially important if your checking IllegalArgumentExceptions assertEquals("the message I get", e.getMessage()); }

assertTrue puede ser un poco fuerte para algunas personas, por lo que assertThat(e.getMessage(), containsString("the message"); puede ser preferible.


Intenté muchos de los métodos aquí, pero eran complicados o no cumplían con mis requisitos. De hecho, uno puede escribir un método auxiliar simplemente:

public class ExceptionAssertions { public static void assertException(BlastContainer blastContainer ) { boolean caughtException = false; try { blastContainer.test(); } catch( Exception e ) { caughtException = true; } if( !caughtException ) { throw new AssertionFailedError("exception expected to be thrown, but was not"); } } public static interface BlastContainer { public void test() throws Exception; } }

Úsalo así:

assertException(new BlastContainer() { @Override public void test() throws Exception { doSomethingThatShouldExceptHere(); } });

Cero dependencias: no hay necesidad de mockito, no hay necesidad de powermock; y funciona bien con las clases finales.


JUnit 4 tiene soporte para esto:

@Test(expected = IndexOutOfBoundsException.class) public void testIndexOutOfBoundsException() { ArrayList emptyList = new ArrayList(); Object o = emptyList.get(0); }

Referencia: https://junit.org/junit4/faq.html#atests_7



Para resolver el mismo problema, configuré un pequeño proyecto: http://code.google.com/p/catch-exception/

Usando este pequeño ayudante escribirías

verifyException(foo, IndexOutOfBoundsException.class).doStuff();

Esto es menos detallado que la regla ExpectedException de JUnit 4.7. En comparación con la solución provista por skaffman, puede especificar en qué línea de código espera la excepción. Espero que esto ayude.


También puedes hacer esto:

@Test public void testFooThrowsIndexOutOfBoundsException() { try { foo.doStuff(); assert false; } catch (IndexOutOfBoundsException e) { assert true; } }


Tenga cuidado al usar la excepción esperada, ya que solo afirma que el método arrojó esa excepción, no una línea de código en particular en la prueba.

Tiendo a usar esto para probar la validación de parámetros, porque tales métodos generalmente son muy simples, pero las pruebas más complejas pueden ser mejor servidas con:

try { methodThatShouldThrow(); fail( "My method didn''t throw when I expected it to" ); } catch (MyException expectedException) { }

Aplicar juicio.


Usando una aserción AssertJ , que se puede usar junto con JUnit:

import static org.assertj.core.api.Assertions.*; @Test public void testFooThrowsIndexOutOfBoundsException() { Foo foo = new Foo(); assertThatThrownBy(() -> foo.doStuff()) .isInstanceOf(IndexOutOfBoundsException.class); }

Es mejor que @Test(expected=IndexOutOfBoundsException.class) porque garantiza que la línea esperada en la prueba arrojó la excepción y le permite verificar más detalles sobre la excepción, como el mensaje, más fácil:

assertThatThrownBy(() -> { throw new Exception("boom!"); }) .isInstanceOf(Exception.class) .hasMessageContaining("boom");

Instrucciones de Maven / Gradle aquí.


Actualización: JUnit5 tiene una mejora para pruebas de excepciones: assertThrows .

El siguiente ejemplo es de: Junit 5 User Guide

@Test void exceptionTesting() { Throwable exception = assertThrows(IllegalArgumentException.class, () -> { throw new IllegalArgumentException("a message"); }); assertEquals("a message", exception.getMessage()); }

Respuesta original usando JUnit 4.

Hay varias formas de probar que se lanza una excepción. También he discutido las opciones a continuación en mi publicación Cómo escribir excelentes pruebas unitarias con JUnit

Establezca el parámetro expected @Test(expected = FileNotFoundException.class) .

@Test(expected = FileNotFoundException.class) public void testReadFile() { myClass.readFile("test.txt"); }

Usando try catch

public void testReadFile() { try { myClass.readFile("test.txt"); fail("Expected a FileNotFoundException to be thrown"); } catch (FileNotFoundException e) { assertThat(e.getMessage(), is("The file test.txt does not exist!")); } }

Pruebas con Regla de ExpectedException .

@Rule public ExpectedException thrown = ExpectedException.none(); @Test public void testReadFile() throws FileNotFoundException { thrown.expect(FileNotFoundException.class); thrown.expectMessage(startsWith("The file test.txt")); myClass.readFile("test.txt"); }

Puede leer más sobre las pruebas de excepciones en el wiki JUnit4 para las pruebas de excepciones y bad.robot - Expecting Exceptions JUnit Rule .


Editar Ahora que JUnit5 ha lanzado, la mejor opción sería usar Assertions.assertThrows() (ver mi otra respuesta ).

Si no ha migrado a JUnit 5, pero puede usar JUnit 4.7, puede usar la Regla ExpectedException :

public class FooTest { @Rule public final ExpectedException exception = ExpectedException.none(); @Test public void doStuffThrowsIndexOutOfBoundsException() { Foo foo = new Foo(); exception.expect(IndexOutOfBoundsException.class); foo.doStuff(); } }

Esto es mucho mejor que @Test(expected=IndexOutOfBoundsException.class) porque la prueba fallará si IndexOutOfBoundsException se lanza antes de foo.doStuff()

Ver este artículo para más detalles.


tl; dr

  • pre-JDK8: recomendaré el antiguo bloque try - catch bueno.

  • post-JDK8: Use AssertJ o lambdas personalizadas para afirmar un comportamiento excepcional .

Independientemente de Junit 4 o JUnit 5.

la larga historia

Es posible que se escriba un bloque try - catch do it yourself o utilice las herramientas JUnit ( @Test(expected = ...) o la función de regla JUnit de @Rule ExpectedException ).

Pero de esta manera no son tan elegantes y no se mezclan bien con otras herramientas.

  1. El bloque try - catch tiene que escribir el bloque alrededor del comportamiento probado, y escribir la aserción en el bloque catch, que puede estar bien, pero muchos encuentran que este estilo interrumpe el flujo de lectura de una prueba. También necesita escribir un Assert.fail al final del bloque try , de lo contrario, la prueba puede perder un lado de las aserciones; PMD , findbugs o Sonar detectarán estos problemas.

  2. La función @Test(expected = ...) es interesante ya que puedes escribir menos código y luego escribir esta prueba es supuestamente menos propenso a errores de codificación. Pero este enfoque carece de algunas áreas.

    • Si la prueba necesita verificar cosas adicionales en la excepción como la causa o el mensaje (los mensajes de buena excepción son realmente importantes, tener un tipo de excepción preciso puede no ser suficiente).
    • Además, a medida que se coloca la expectativa en el método, dependiendo de cómo se escriba el código probado, la parte incorrecta del código de prueba puede generar la excepción, lo que lleva a una prueba de falsos positivos y no estoy seguro de que PMD , findbugs o Sonar darán consejos sobre dicho código.

      @Test(expected = WantedException.class) public void call2_should_throw_a_WantedException__not_call1() { // init tested tested.call1(); // may throw a WantedException // call to be actually tested tested.call2(); // the call that is supposed to raise an exception }

  3. La regla ExpectedException también es un intento de solucionar las advertencias anteriores, pero es un poco incómodo de usar, ya que utiliza un estilo de expectativa, los usuarios de EasyMock conocen muy bien este estilo. Puede ser conveniente para algunos, pero si sigue los principios de Behavior Driven Development (BDD) o Arrange Act Assert (AAA), la regla ExpectedException no se ajustará a esos estilos de escritura. Aparte de eso, puede sufrir el mismo problema que la forma @Test , dependiendo de dónde se coloque la expectativa.

    @Rule ExpectedException thrown = ExpectedException.none() @Test public void call2_should_throw_a_WantedException__not_call1() { // expectations thrown.expect(WantedException.class); thrown.expectMessage("boom"); // init tested tested.call1(); // may throw a WantedException // call to be actually tested tested.call2(); // the call that is supposed to raise an exception }

    Incluso la excepción esperada se coloca antes de la declaración de prueba, rompe su flujo de lectura si las pruebas siguen BDD o AAA.

    También vea este tema de comment en JUnit del autor de ExpectedException .

Así que estas opciones anteriores tienen toda su carga de advertencias, y claramente no son inmunes a los errores del codificador.

  1. Hay un proyecto del que me di cuenta después de crear esta respuesta que parece prometedor, es catch-exception .

    Como dice la descripción del proyecto, le permite a un codificador escribir en una línea de código fluida que captura la excepción y ofrece esta excepción para una posterior afirmación. Y puede usar cualquier biblioteca de aserciones como Hamcrest o AssertJ .

    Un ejemplo rápido tomado de la página de inicio:

    // given: an empty list List myList = new ArrayList(); // when: we try to get the first element of the list when(myList).get(1); // then: we expect an IndexOutOfBoundsException then(caughtException()) .isInstanceOf(IndexOutOfBoundsException.class) .hasMessage("Index: 1, Size: 0") .hasNoCause();

    Como puede ver, el código es realmente sencillo, captura la excepción en una línea específica, la API es un alias que usará las API de AssertJ (similar a usar assertThat(ex).hasNoCause()... ). En algún momento el proyecto se basó en FEST-Assert, el antepasado de AssertJ . EDITAR: Parece que el proyecto está elaborando un soporte de Java 8 Lambdas.

    Actualmente esta biblioteca tiene dos defectos:

    • Al momento de escribir este artículo, es importante mencionar que esta biblioteca se basa en Mockito 1.x, ya que crea un simulacro del objeto probado detrás de la escena. Como Mockito aún no está actualizado, esta biblioteca no puede trabajar con clases finales o métodos finales . E incluso si estuviera basado en mockito 2 en la versión actual, esto requeriría declarar un fabricante de simulacros global ( inline-mock-maker ), algo que puede que no sea lo que quieres, ya que este mockmaker tiene diferentes inconvenientes que el mockmaker habitual.

    • Requiere otra dependencia de prueba.

    Estos problemas no se aplicarán una vez que la biblioteca admita lambdas, sin embargo, la funcionalidad será duplicada por el conjunto de herramientas AssertJ.

    Teniendo todo en cuenta si no desea utilizar la herramienta de excepción de captura, recomendaré la forma correcta y antigua del bloque try - catch , al menos hasta el JDK7. Y para los usuarios de JDK 8, es posible que prefiera usar AssertJ, ya que ofrece más que solo afirmar excepciones.

  2. Con el JDK8, los lambdas entran en la escena de prueba y han demostrado ser una forma interesante de afirmar un comportamiento excepcional. AssertJ se ha actualizado para proporcionar una buena API fluida para afirmar un comportamiento excepcional.

    Y una prueba de muestra con AssertJ :

    @Test public void test_exception_approach_1() { ... assertThatExceptionOfType(IOException.class) .isThrownBy(() -> someBadIOOperation()) .withMessage("boom!"); } @Test public void test_exception_approach_2() { ... assertThatThrownBy(() -> someBadIOOperation()) .isInstanceOf(Exception.class) .hasMessageContaining("boom"); } @Test public void test_exception_approach_3() { ... // when Throwable thrown = catchThrowable(() -> someBadIOOperation()); // then assertThat(thrown).isInstanceOf(Exception.class) .hasMessageContaining("boom"); }

  3. Con una reescritura casi completa de JUnit 5, las afirmaciones se han improved un poco, pueden resultar interesantes como una forma inmediata para afirmar correctamente la excepción. Pero en realidad la API de aserción todavía es un poco deficiente, no hay nada fuera de assertThrows .

    @Test @DisplayName("throws EmptyStackException when peeked") void throwsExceptionWhenPeeked() { Throwable t = assertThrows(EmptyStackException.class, () -> stack.peek()); Assertions.assertEquals("...", t.getMessage()); }

    Como ha notado, assertEquals sigue devolviéndose void , y como tal no permite encadenar aserciones como AssertJ.

    Además, si recuerdas el choque de nombres con Matcher o Assert , prepárate para enfrentar el mismo choque con Assertions .

Me gustaría concluir que hoy (2017-03-03) la facilidad de uso, la API detectable , el rápido ritmo de desarrollo de AssertJ y la dependencia de prueba de facto es la mejor solución con JDK8 independientemente del marco de prueba (JUnit o no), los JDK anteriores deberían depender de catch bloques try - catch incluso si se sienten torpes.

Esta respuesta ha sido copiada de otra pregunta que no tiene la misma visibilidad, yo soy el mismo autor.


Con Java 8 puede crear un método tomando un código para verificar y esperar una excepción como parámetros:

private void expectException(Runnable r, Class<?> clazz) { try { r.run(); fail("Expected: " + clazz.getSimpleName() + " but not thrown"); } catch (Exception e) { if (!clazz.isInstance(e)) fail("Expected: " + clazz.getSimpleName() + " but " + e.getClass().getSimpleName() + " found", e); } }

y luego dentro de tu prueba:

expectException(() -> list.sublist(0, 2).get(2), IndexOutOfBoundsException.class);

Beneficios:

  • sin depender de ninguna biblioteca
  • control localizado: más preciso y permite tener múltiples aseveraciones como esta dentro de una prueba si es necesario
  • fácil de usar

En JUnit 4 o posterior puedes probar las excepciones de la siguiente manera

@Rule public ExpectedException exceptions = ExpectedException.none();


Esto proporciona muchas características que se pueden usar para mejorar nuestras pruebas JUnit.
Si ve el siguiente ejemplo, estoy probando 3 cosas en la excepción.

  1. El tipo de excepción arrojado
  2. El mensaje de excepción
  3. La causa de la excepción.


public class MyTest { @Rule public ExpectedException exceptions = ExpectedException.none(); ClassUnderTest classUnderTest; @Before public void setUp() throws Exception { classUnderTest = new ClassUnderTest(); } @Test public void testAppleisSweetAndRed() throws Exception { exceptions.expect(Exception.class); exceptions.expectMessage("this is the exception message"); exceptions.expectCause(Matchers.<Throwable>equalTo(exceptionCause)); classUnderTest.methodUnderTest("param1", "param2"); } }


Hay dos formas de escribir un caso de prueba

  1. Anote la prueba con la excepción que es lanzada por el método. Algo como esto@Test(expected = IndexOutOfBoundsException.class)
  2. Simplemente puede capturar la excepción en la clase de prueba utilizando el bloque try catch y afirmar en el mensaje que se arroja desde el método en la clase de prueba.

    try{ } catch(exception to be thrown from method e) { assertEquals("message", e.getmessage()); }

Espero que esto responda a su consulta Feliz aprendizaje ...


La solución Junit4 con Java8 es usar esta función:

public Throwable assertThrows(Class<? extends Throwable> expectedException, java.util.concurrent.Callable<?> funky) { try { funky.call(); } catch (Throwable e) { if (expectedException.isInstance(e)) { return e; } throw new AssertionError( String.format("Expected [%s] to be thrown, but was [%s]", expectedException, e)); } throw new AssertionError( String.format("Expected [%s] to be thrown, but nothing was thrown.", expectedException)); }

El uso es entonces:

assertThrows(ValidationException.class, () -> finalObject.checkSomething(null));

Tenga en cuenta que la única limitación es utilizar una finalreferencia de objeto en la expresión lambda. Esta solución permite continuar con las aseveraciones de prueba en lugar de esperar que Thowable a nivel de método use la @Test(expected = IndexOutOfBoundsException.class)solución.


Mi solución utilizando Java 8 lambdas:

public static <T extends Throwable> T assertThrows(Class<T> expected, ThrowingRunnable action) throws Throwable { try { action.run(); Assert.fail("Did not throw expected " + expected.getSimpleName()); return null; // never actually } catch (Throwable actual) { if (!expected.isAssignableFrom(actual.getClass())) { // runtime ''!(actual instanceof expected)'' System.err.println("Threw " + actual.getClass().getSimpleName() + ", which is not a subtype of expected " + expected.getSimpleName()); throw actual; // throw the unexpected Throwable for maximum transparency } else { return (T) actual; // return the expected Throwable for further examination } } }

Tienes que definir un FunctionalInterface, porque Runnableno declara lo requerido throws.

@FunctionalInterface public interface ThrowingRunnable { void run() throws Throwable; }

El método se puede utilizar de la siguiente manera:

class CustomException extends Exception { public final String message; public CustomException(final String message) { this.message = message;} } CustomException e = assertThrows(CustomException.class, () -> { throw new CustomException("Lorem Ipsum"); }); assertEquals("Lorem Ipsum", e.message);


Podemos usar un error de aserción después del método que debe devolver una excepción:

try{ methodThatThrowMyException(); Assert.fail("MyException is not thrown !"); } catch (final Exception exception) { // Verify if the thrown exception is instance of MyException, otherwise throws an assert failure assertTrue(exception instanceof MyException, "An exception other than MyException is thrown !"); // In case of verifying the error message MyException myException = (MyException) exception; assertEquals("EXPECTED ERROR MESSAGE", myException.getMessage()); }


Solo crea un Matcher que pueda ser activado y desactivado de la siguiente manera:

public class ExceptionMatcher extends BaseMatcher<Throwable> { private boolean active = true; private Class<? extends Throwable> throwable; public ExceptionMatcher(Class<? extends Throwable> throwable) { this.throwable = throwable; } public void on() { this.active = true; } public void off() { this.active = false; } @Override public boolean matches(Object object) { return active && throwable.isAssignableFrom(object.getClass()); } @Override public void describeTo(Description description) { description.appendText("not the covered exception type"); } }

Para usarlo:

agregue public ExpectedException exception = ExpectedException.none();, entonces:

ExceptionMatcher exMatch = new ExceptionMatcher(MyException.class); exception.expect(exMatch); someObject.somethingThatThrowsMyException(); exMatch.off();


Tomemos, por ejemplo, que desea escribir Junit para el fragmento de código mencionado a continuación.

public int divideByZeroDemo(int a,int b){ return a/b; } public void exceptionWithMessage(String [] arr){ throw new ArrayIndexOutOfBoundsException("Array is out of bound"); }

El código anterior es para probar alguna excepción desconocida que pueda ocurrir y la siguiente es para hacer valer alguna excepción con un mensaje personalizado.

@Rule public ExpectedException exception=ExpectedException.none(); private Demo demo; @Before public void setup(){ demo=new Demo(); } @Test(expected=ArithmeticException.class) public void testIfItThrowsAnyException() { demo.divideByZeroDemo(5, 0); } @Test public void testExceptionWithMessage(){ exception.expectMessage("Array is out of bound"); exception.expect(ArrayIndexOutOfBoundsException.class); demo.exceptionWithMessage(new String[]{"This","is","a","demo"}); }


Además de lo que ha dicho , asegúrese de que:

  • La instancia ExpectedException es pública ( pregunta relacionada )
  • La ExpectedException no está instanciada en, por ejemplo, el método @Before. Este post explica claramente todas las complejidades de la orden de ejecución de JUnit.

No no hacer esto:

@Rule public ExpectedException expectedException; @Before public void setup() { expectedException = ExpectedException.none(); }

Finalmente, this publicación de blog ilustra claramente cómo afirmar que se produce una cierta excepción.


En mi caso, siempre recibo RuntimeException de db, pero los mensajes difieren. Y la excepción debe ser manejada respectivamente. Aquí es cómo lo probé:

@Test public void testThrowsExceptionWhenWrongSku() { // Given String articleSimpleSku = "999-999"; int amountOfTransactions = 1; Exception exception = null; // When try { createNInboundTransactionsForSku(amountOfTransactions, articleSimpleSku); } catch (RuntimeException e) { exception = e; } // Then shouldValidateThrowsExceptionWithMessage(exception, MESSAGE_NON_EXISTENT_SKU); } private void shouldValidateThrowsExceptionWithMessage(final Exception e, final String message) { assertNotNull(e); assertTrue(e.getMessage().contains(message)); }


La respuesta más flexible y elegante para Junit 4 que encontré en el blog Mkyong . Tiene la flexibilidad de try/catchutilizar la @Ruleanotación. Me gusta este enfoque porque puede leer atributos específicos de una excepción personalizada.

package com.mkyong; import com.mkyong.examples.CustomerService; import com.mkyong.examples.exception.NameNotFoundException; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; import static org.hamcrest.CoreMatchers.containsString; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.Matchers.hasProperty; public class Exception3Test { @Rule public ExpectedException thrown = ExpectedException.none(); @Test public void testNameNotFoundException() throws NameNotFoundException { //test specific type of exception thrown.expect(NameNotFoundException.class); //test message thrown.expectMessage(is("Name is empty!")); //test detail thrown.expect(hasProperty("errCode")); //make sure getters n setters are defined. thrown.expect(hasProperty("errCode", is(666))); CustomerService cust = new CustomerService(); cust.findByName(""); } }


Recomiendo biblioteca assertj-corepara manejar excepción en prueba de junit

En java 8, así:

//given //when Throwable throwable = catchThrowable(() -> anyService.anyMethod(object)); //then AnyException anyException = (AnyException) throwable; assertThat(anyException.getMessage()).isEqualTo("........"); assertThat(exception.getCode()).isEqualTo(".......);