¿Cómo se afirma que una cierta excepción se lanza en las pruebas de JUnit 4?
¿Cómo puedo usar JUnit4 idiomáticamente para probar que algún código arroja 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 una Aserción.xyz o algo que es mucho menos desacoplados y mucho más en el espíritu de JUnit para este tipo de situaciones.
30 answers
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
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-04-18 05:27:06
Editar Ahora que JUnit5 ha sido 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 el ExpectedException
Regla:
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
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-10-01 16:43:56
Tenga cuidado al usar la excepción esperada, porque solo afirma que el método lanzó 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 suelen ser muy simples, pero las pruebas más complejas podrían servirse mejor con:
try {
methodThatShouldThrow();
fail( "My method didn't throw when I expected it to" );
} catch (MyException expectedException) {
}
Aplicar sentencia.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-10-01 09:36:52
Como se respondió antes, hay muchas maneras de lidiar con las excepciones en JUnit. Pero con Java 8 hay otra: usar expresiones Lambda. Con expresiones Lambda 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 que la interfaz esperará y estará lista para manejar una excepción.
Esto es relativamente simple pero una técnica poderosa.
Echa un vistazo a esta entrada 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.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-11-27 15:07:00
En junit, hay cuatro formas de probar la excepción.
-
Para junit4.x, utilice el atributo opcional "esperado" de la anotación de prueba
@Test(expected = IndexOutOfBoundsException.class) public void testFooThrowsIndexOutOfBoundsException() { foo.doStuff(); }
-
Para junit4.x, utilice 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 usar la clásica manera de probar / atrapar ampliamente utilizada en junit 3 framework
@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 de la siguiente manera
@Test public void testFooThrowsIndexOutOfBoundsException() { Throwable exception = assertThrows(IndexOutOfBoundsException.class, () -> foo.doStuff()); assertEquals("expected messages", exception.getMessage()); }
-
So
- el 1er camino es se usa cuando solo se desea probar el tipo de excepción
- las otras tres formas se utilizan cuando desea probar el mensaje de excepción más
- si usa junit 3, entonces se prefiere el 3er
- si te gusta junit 5, entonces debería gustarte el 4th one
Para más información, puede leer este documento y la guía del usuario de junit5 para más detalles.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-06-08 13:53:58
Tl; dr
Pre-JDK8: Recomendaré el viejo bien
try
-catch
bloquear.Post-JDK8: Use AssertJ o lambdas personalizadas para afirmar un comportamiento excepcional.
Independientemente de Junit 4 o JUnit 5.
La larga historia
Es posible escribir usted mismo un hágalo usted mismo try
-catch
bloquear o usar las herramientas JUnit (@Test(expected = ...)
o la regla JUnit @Rule ExpectedException
función).
Pero estas formas no son tan elegantes y no se mezclan bien en cuanto a legibilidad con otras herramientas.
Las
try
-catch
bloque tienes que escribir el bloque alrededor del comportamiento probado, y escribir la afirmació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 unAssert.fail
al final del bloquetry
de lo contrario la prueba puede perder un lado de las aserciones; PMD , findbugs o Sonar va a detectar problemas.-
La característica
@Test(expected = ...)
es interesante ya que puede 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 buenos mensajes de excepción son realmente importantes, tener un tipo de excepción preciso puede no ser suficiente).
-
También como la expectativa se coloca alrededor en el método, dependiendo de cómo se escribe el código probado, entonces la parte incorrecta del código de prueba puede lanzar la excepción, lo que lleva a una prueba positiva falsa y no estoy seguro de que PMD, findbugs o Sonar darán pistas 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 }
-
La regla
ExpectedException
también es un intento de corregir las advertencias anteriores, pero se siente un poco incómodo de usar, ya que utiliza una expectativa style, Los usuarios de EasyMock conocen muy bien este estilo. Podría ser conveniente para algunos, pero si sigues los principios Behaviour Driven Development (BDD) o Arrange Act Assert (AAA), la reglaExpectedException
no encajará en esos estilos de escritura. Aparte de eso, puede sufrir el mismo problema que el camino@Test
, dependiendo de dónde coloques 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 instrucción de prueba, rompe su flujo de lectura si el las pruebas siguen BDD o AAA.
Ver también este comentario número sobre JUnit del autor de
ExpectedException
.
Así que estas opciones anteriores tienen toda su carga de advertencias, y claramente no son inmunes a los errores de codificador.
-
Hay un proyecto que me di cuenta después de crear esta respuesta que parece prometedor, es excepción de captura.
Como dice la descripción del proyecto, permite que un codificador escriba una línea de código fluida captura de la excepción y ofrecer esta excepción para la afirmación posterior. Y puedes 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, se captura la excepción en una línea específica, la API
then
es un alias que usará API AssertJ (similar a usarassertThat(ex).hasNoCause()...
). En algún momento el proyecto se basó en FEST-Assert el antepasado de AssertJ. EDITAR: Parece que el proyecto está preparando un soporte para Java 8 Lambdas.Actualmente esta biblioteca tiene dos deficiencias:
En el momento de escribir este artículo es digno de mención decir que esta biblioteca está basada en Mockito 1.x, ya que crea una simulación del objeto probado detrás de la escena. Como Mockito todavía no está actualizado esta biblioteca no puede funcionar con clases finales o métodos finales. E incluso si se basa en mockito 2 en la versión actual, esto requeriría declarar un mockmaker global (
inline-mock-maker
), algo que puede no ser lo que quieres, ya que este mockmaker tiene diferentes inconvenientes que el mockmaker regular.Requiere otra dependencia de prueba.
Estos problemas no se aplicarán una vez que la biblioteca soporte lambdas, sin embargo la funcionalidad será duplicada por AssertJ toolset.
Teniendo todo en cuenta si no desea utilizar la herramienta de excepción de captura, recomendaré la vieja buena manera de las
try
-catch
bloque, 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. -
Con el JDK8, las 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 API fluida agradable 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"); }
-
Con a casi reescritura completa de JUnit 5, las aserciones han sido mejoradas un poco, pueden resultar interesantes como una forma lista para usar de afirmar correctamente la excepción. Pero realmente la API de aserción sigue siendo un poco pobre, no hay nada afuera
assertThrows
.@Test @DisplayName("throws EmptyStackException when peeked") void throwsExceptionWhenPeeked() { Throwable t = assertThrows(EmptyStackException.class, () -> stack.peek()); Assertions.assertEquals("...", t.getMessage()); }
Como has notado,
assertEquals
todavía está regresandovoid
, y como tal no permite encadenar aserciones como AssertJ.También si recuerdas el choque de nombres con
Matcher
oAssert
, prepárate para enfrentar el mismo choque porAssertions
.
Me gustaría concluir que hoy (2017-03-03) La facilidad de uso de AssertJ, la API detectable, el rápido ritmo de desarrollo y como una dependencia de prueba de facto es la mejor solución con JDK8, independientemente del marco de prueba (JUnit o no), los JDKs anteriores deberían confiar entry
-catch
bloquea incluso si se sienten torpes.
Esta respuesta ha sido copiada de otra pregunta que no tiene la misma visibilidad, soy el mismo autor.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-07-05 08:51:46
Qué tal esto: Captura una excepción muy general, asegúrate de que salga del bloque catch, luego afirma que la clase de la excepción es lo que esperas que sea. Esta afirmación fallará si a) la excepción es del tipo incorrecto (eg. si tienes un puntero nulo en su lugar) y b) la excepción nunca fue lanzada.
public void testFooThrowsIndexOutOfBoundsException() {
Throwable e = null;
try {
foo.doStuff();
} catch (Throwable ex) {
e = ex;
}
assertTrue(e instanceof IndexOutOfBoundsException);
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-11-13 00:22:07
Solución de estilo BDD : JUnit 4 + Excepción de Captura + AssertJ
@Test
public void testFooThrowsIndexOutOfBoundsException() {
when(foo).doStuff();
then(caughtException()).isInstanceOf(IndexOutOfBoundsException.class);
}
Código fuente
Dependencias
eu.codearte.catch-exception:catch-exception:1.3.3
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-01-08 19:35:25
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 la línea esperada en la prueba arrojó la excepción y le permite verificar más detalles sobre la excepción, como mensaje, más fácil:
assertThatThrownBy(() ->
{
throw new Exception("boom!");
})
.isInstanceOf(Exception.class)
.hasMessageContaining("boom");
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-10-11 18:24:43
Ahora que JUnit 5 ha lanzado, la mejor opción es usar Assertions.assertThrows()
(ver
la Guía del Usuario Junit 5).
Aquí hay un ejemplo que verifica que se lanza una excepción, y usa Truth para hacer afirmaciones sobre 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:
- Integrado en JUnit
- Se obtiene un mensaje de excepción útil si el código en la lambda no lanza una excepción, y una stacktrace si lanza una excepción diferente
- Conciso
- Permite que sus pruebas sigan Arrange-Act-Assert
- Puede indicar con precisión qué código espera lanzar la excepción
- No es necesario enumerar la excepción esperada en la cláusula
throws
- Puede usar el marco de aserciones de su elección para hacer aserciones sobre la excepción capturada
Se agregará un método similar a org.junit Assert
en JUnit 4.13.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-10-01 17:17:00
Para resolver el mismo problema que hice configurar 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 proporcionada por skaffman, puede especificar en qué línea de código espera la excepción. Espero que esto ayude.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-10-28 09:26:21
Actualización: JUnit5 tiene una mejora para probar excepciones: assertThrows
.
El siguiente ejemplo es de: Guía del usuario de Junit 5
@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 maneras de probar que una excepción es lanzada. También he discutido las siguientes opciones en mi post Cómo escribir grandes pruebas unitarias con JUnit
Establece 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!"));
}
}
Probando con la regla 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");
}
Puedes leer más sobre las pruebas de excepciones en wiki de JUnit4 para las pruebas de excepciones y mal.robot-Esperando excepciones JUnit Rule .
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-01-05 16:03:12
También puedes hacer esto:
@Test
public void testFooThrowsIndexOutOfBoundsException() {
try {
foo.doStuff();
assert false;
} catch (IndexOutOfBoundsException e) {
assert true;
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-11-13 00:21:01
En mi humilde opinión, la mejor manera de comprobar 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());
}
El assertTrue
podría ser un poco fuerte para algunas personas, por lo que assertThat(e.getMessage(), containsString("the message");
podría ser preferible.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-03-14 18:07:21
Solución de 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 http://junit.org/junit5/docs/current/user-guide/#writing-tests-assertions
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-07-24 15:00:31
Probé muchos de los métodos aquí, pero eran complicados o no cumplían mis requisitos. De hecho, uno puede escribir un método helper 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.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-10-10 15:02:44
JUnit tiene soporte incorporado para esto, con un atributo "esperado"
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-10-01 07:05:49
Solución Java 8
Si desea una solución que:
- Utiliza Java 8 lambdas
- Does not depend on any JUnit magic
- Le permite verificar múltiples excepciones dentro de un único 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 examinar más a fondo it
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.
}
Utilícelo como sigue:
@Test
public void testThrows()
{
RuntimeException e = expectException( RuntimeException.class, () ->
{
throw new RuntimeException( "fail!" );
} );
assert e.getMessage().equals( "fail!" );
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-02-11 16:38:50
En mi caso siempre obtengo RuntimeException de la base de datos, pero los mensajes difieren. Y la excepción necesita ser manejada respectivamente. Así es como 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));
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-07-02 09:03:57
En JUnit 4 o posterior puede probar las excepciones de la siguiente manera
@Rule
public ExpectedException exceptions = ExpectedException.none();
esto proporciona una gran cantidad de características que se pueden utilizar para mejorar nuestras pruebas JUnit.
Si ves el siguiente ejemplo, estoy probando 3 cosas en la excepción.
- El tipo de excepción lanzada
- El Mensaje de excepción
- 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");
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-12-08 05:48:19
Podemos usar una aserción fail 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());
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-12-20 10:34:05
La respuesta más flexible y elegante para Junit 4 que encontré en el blog Mkyoung. Tiene la flexibilidad de try/catch
usando la anotación @Rule
. Me gustó este enfoque porque ya necesitaba 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("");
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-08-06 13:17:09
Además de lo que NamShubWriter ha dicho, asegúrese de que:
- La instancia ExpectedException es pública (Pregunta conexa)
- La ExpectedException no es instanciada en digamos, el método @Before. Este post explica claramente todas las complejidades de la orden de ejecución de JUnit.
Haz no haz esto:
@Rule
public ExpectedException expectedException;
@Before
public void setup()
{
expectedException = ExpectedException.none();
}
Finalmente, esta entrada de blog ilustra claramente cómo afirmar que un se lanza cierta excepción.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:18:24
Simplemente haga un Matcher que pueda ser apagado y encendido, así:
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:
Añadir public ExpectedException exception = ExpectedException.none();
,
entonces:
ExceptionMatcher exMatch = new ExceptionMatcher(MyException.class);
exception.expect(exMatch);
someObject.somethingThatThrowsMyException();
exMatch.off();
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-03-02 02:28:41
Tome por ejemplo, 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 el siguiente es para afirmar 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"});
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-10-29 07:34:18
Con Java 8 puede crear un método tomando un código para verificar y la excepción esperada 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 su prueba:
expectException(() -> list.sublist(0, 2).get(2), IndexOutOfBoundsException.class);
Beneficios:
- no depender de ninguna biblioteca
- control localizado-más preciso y permite tener múltiples aserciones como esta dentro de una prueba si es necesario
- fácil de usar
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-10-01 12:03:38
Mi solución usando 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 una interfaz funcional, porque Runnable
no declara el throws
requerido.
@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);
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-10-04 12:03:26
Hay dos formas de escribir el caso de prueba
- Anote la prueba con la excepción que arroja el método. Algo como esto
@Test(expected = IndexOutOfBoundsException.class)
-
Simplemente puede capturar la excepción en la clase de prueba usando el bloque try catch y afirmar en el mensaje que se lanza 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 pregunta Feliz aprendizaje...
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-11-09 07:23:04
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 usar una referencia de objeto final
en la expresión lambda.
Esta solución permite continuar las aserciones de prueba en lugar de esperar thowable a nivel de método utilizando @Test(expected = IndexOutOfBoundsException.class)
solución.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-04-06 16:32:25
Recomiendo la biblioteca assertj-core
para manejar la excepción en junit test
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(".......);
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-07-18 11:32:37