Como você afirma que uma certa exceção é lançada nos testes da JUnit 4?

Como posso usar o JUnit4 idiomaticamente para testar se algum código gera uma exceção?

Embora eu certamente possa fazer algo assim:

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

Lembro-me de que há uma anotação ou um Assert.xyz ou algo que é muito menos desajeitado e muito mais no espírito da JUnit para esses tipos de situações.

   

    O JUnit 4 tem suporte para isso:

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

    Referência: https://junit.org/junit4/faq.html#atests_7

    Edit Agora que o JUnit5 foi lançado, a melhor opção seria usar Assertions.assertThrows() (veja minha outra resposta ).

    Se você ainda não migrou para o JUnit 5, mas pode usar o JUnit 4.7, é possível usar a regra 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(); } } 

    Isso é muito melhor que @Test(expected=IndexOutOfBoundsException.class) porque o teste falhará se IndexOutOfBoundsException for lançado antes de foo.doStuff()

    Veja este artigo para detalhes

    Tenha cuidado ao usar a exceção esperada, porque ela só afirma que o método emitiu essa exceção, não uma linha de código específica no teste.

    Eu costumo usar isso para testar a validação de parâmetros, porque esses methods são geralmente muito simples, mas testes mais complexos podem ser melhorados com:

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

    Aplicar julgamento.

    Como foi respondido anteriormente, há muitas maneiras de lidar com exceções no JUnit. Mas com o Java 8 há outro: usando expressões lambda. Com o Lambda Expressions, podemos obter uma syntax 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 aceita uma interface funcional, cujas instâncias podem ser criadas com expressões lambda, referências de método ou referências de construtor. assertThrown aceitando que a interface esperará e estará pronta para manipular uma exceção.

    Esta é uma técnica relativamente simples, mas poderosa.

    Dê uma olhada neste post do blog descrevendo esta técnica: http://blog.codeleak.pl/2014/07/junit-testing-exception-with-java-8-and-lambda-expressions.html

    O código-fonte pode ser encontrado aqui: https://github.com/kolorobot/unit-testing-demo/tree/master/src/test/java/com/github/kolorobot/exceptions/java8

    Divulgação: Eu sou o autor do blog e do projeto.

    no junit, existem quatro maneiras de testar a exceção.

    • para junit4.x, use o atributo ‘esperado’ opcional de annonation de teste

       @Test(expected = IndexOutOfBoundsException.class) public void testFooThrowsIndexOutOfBoundsException() { foo.doStuff(); } 
    • para junit4.x, use a regra 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(); } } 
    • você também pode usar a maneira clássica de tentar / pegar amplamente usada no framework 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, você também pode usar assertThrows da seguinte forma

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

      • a primeira maneira é usada quando você quer apenas testar o tipo de exceção
      • as outras três formas são usadas quando você deseja testar a mensagem de exceção mais
      • se você usa junit 3, então o terceiro é o preferido
      • se você gosta do junit 5, então você deveria gostar do 4º
    • para mais informações, você pode ler este documento e o guia do usuário junit5 para obter detalhes.

    tl; dr

    • pré-JDK8: Eu recomendarei o antigo bom bloqueio trycatch .

    • post-JDK8: Use AssertJ ou lambdas personalizados para determinar um comportamento excepcional .

    Independentemente do Junit 4 ou JUnit 5.

    a longa história

    É possível escrever para você mesmo um bloco trycatch ou use as ferramentas JUnit ( @Test(expected = ...) ou o recurso de regra @Rule ExpectedException JUnit).

    Mas estes caminhos não são tão elegantes e não combinam bem a leitura com outras ferramentas.

    1. O bloco trycatch você tem que escrever o bloco em torno do comportamento testado, e escrever a asserção no bloco catch, que pode ser bom, mas muitos acham que esse estilo interrompe o stream de leitura de um teste. Além disso, você precisa escrever um Assert.fail no final do bloco try , caso contrário, o teste pode perder um lado das asserções; PMD , findbugs ou Sonar identificarão esses problemas.

    2. O recurso @Test(expected = ...) é interessante, pois você pode escrever menos código e, em seguida, escrever esse teste é supostamente menos propenso a erros de codificação. Mas esta abordagem está faltando algumas áreas.

      • Se o teste precisar verificar itens adicionais na exceção, como a causa ou a mensagem (boas mensagens de exceção são realmente importantes, ter um tipo de exceção preciso pode não ser suficiente).
      • Além disso, como a expectativa é colocada no método, dependendo de como o código testado é escrito, a parte errada do código de teste pode lançar a exceção, levando a um falso positivo e não tenho certeza se o PMD , findbugs ou Sonar fornecerá dicas sobre esse 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. A regra ExpectedException também é uma tentativa de corrigir as advertências anteriores, mas parece um pouco complicado de usar, pois usa um estilo de expectativa, os usuários do EasyMock conhecem muito bem esse estilo. Pode ser conveniente para alguns, mas se você seguir os princípios Behavior Driven Development (BDD) ou Arrange Act Assert (AAA), a regra ExpectedException não se ajustará ao estilo de escrita. Além disso, ele pode sofrer o mesmo problema que o da maneira @Test , dependendo de onde você coloca a 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 } 

      Mesmo a exceção esperada é colocada antes da instrução de teste, ela interrompe o stream de leitura se os testes seguirem BDD ou AAA.

      Veja também este comentário no JUnit do autor de ExpectedException .

    Então, essas opções acima têm toda a sua carga de advertências, e claramente não estão imunes aos erros do codificador.

    1. Há um projeto que tomei conhecimento depois de criar essa resposta que parece promissora, é exceção de captura .

      Como diz a descrição do projeto, ele permite que um codificador escreva uma linha fluente de código capturando a exceção e ofereça essa exceção para uma afirmação posterior. E você pode usar qualquer biblioteca de asserções como Hamcrest ou AssertJ .

      Um exemplo rápido retirado da home page:

       // 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 você pode ver que o código é realmente direto, você captura a exceção em uma linha específica, then API é um alias que usará APIs AssertJ (semelhante a assertThat(ex).hasNoCause()... ). Em algum momento o projeto confiou no FEST-Assert o ancestral de AssertJ . EDIT: Parece que o projeto está se formando um suporte a Java 8 Lambdas.

      Atualmente esta biblioteca tem duas deficiências:

      • No momento em que este texto foi escrito, é digno de nota dizer que esta biblioteca é baseada no Mockito 1.x, pois cria uma simulação do object testado por trás da cena. Como Mockito ainda não está atualizado, esta biblioteca não pode trabalhar com classs finais ou methods finais . E mesmo se fosse baseado em mockito 2 na versão atual, isso exigiria a declaração de um mock maker global ( inline-mock-maker ), algo que pode não ser o que você quer, já que este mockmaker tem desvantagens diferentes do mockmaker regular.

      • Requer ainda outra dependência de teste.

      Esses problemas não serão aplicados uma vez que a biblioteca suportará lambdas, no entanto, a funcionalidade será duplicada pelo conjunto de ferramentas AssertJ.

      Levando tudo em conta se você não quiser usar a ferramenta de exceção de captura, eu recomendarei a antiga boa maneira do bloco trycatch , pelo menos até o JDK7. E para usuários do JDK 8, você pode preferir usar o AssertJ, já que ele oferece mais do que apenas declarar exceções.

    2. Com o JDK8, lambdas entram na cena de teste e provaram ser uma maneira interessante de afirmar um comportamento excepcional. AssertJ foi atualizado para fornecer uma boa API fluente para garantir um comportamento excepcional.

      E um teste de amostra com 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. Com uma reescrita quase completa do JUnit 5, as asserções foram melhoradas um pouco, elas podem ser interessantes como uma maneira pronta para afirmar corretamente a exceção. Mas realmente a API de asserção ainda é um pouco ruim, não há nada fora do assertThrows .

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

      Como você percebeu, assertEquals ainda está retornando void e, como tal, não permite encadear afirmações como AssertJ.

      Além disso, se você se lembrar do confronto de nome com o Matcher ou o Assert , esteja preparado para enfrentar o mesmo confronto com as Assertions .

    Eu gostaria de concluir que hoje (2017-03-03) a facilidade de uso do AssertJ , API detectável, ritmo rápido de desenvolvimento e como dependência de teste de fato é a melhor solução com o JDK8 independentemente da estrutura de teste (JUnit ou não), os JDKs anteriores devem confiar nos blocos trycatch , mesmo que se sintam desajeitados.

    Esta resposta foi copiada de outra pergunta que não tem a mesma visibilidade, eu sou o mesmo autor.

    Que tal isso: Pegue uma exceção muito geral, certifique-se de que ela saia do bloco catch e, em seguida, declare que a class da exceção é o que você espera que seja. Esta declaração falhará se a) a exceção for do tipo errado (por exemplo, se você tiver um Null Pointer) e b) a exceção nunca foi lançada.

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

    Solução de estilo BDD : JUnit 4 + captura de exceção + AssertJ

     @Test public void testFooThrowsIndexOutOfBoundsException() { when(foo).doStuff(); then(caughtException()).isInstanceOf(IndexOutOfBoundsException.class); } 

    Código fonte

    Dependências

     eu.codearte.catch-exception:catch-exception:1.3.3 

    Usando uma afirmação AssertJ , que pode ser usada ao lado do JUnit:

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

    É melhor que @Test(expected=IndexOutOfBoundsException.class) porque garante que a linha esperada no teste emitiu a exceção e permite verificar mais detalhes sobre a exceção, como mensagem, mais fácil:

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

    Instruções Maven / Gradle aqui.

    Para resolver o mesmo problema, criei um pequeno projeto: http://code.google.com/p/catch-exception/

    Usando este pequeno ajudante você escreveria

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

    Isso é menos detalhado que a regra ExpectedException do JUnit 4.7. Em comparação com a solução fornecida pelo skaffman, você pode especificar em qual linha de código você espera a exceção. Eu espero que isso ajude.

    Agora que o JUnit 5 foi lançado, a melhor opção é usar Assertions.assertThrows() (consulte o Guia do Usuário do Junit 5 ).

    Aqui está um exemplo que verifica que uma exceção é lançada e usa a Verdade para fazer asserções na mensagem de exceção:

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

    As vantagens sobre as abordagens nas outras respostas são:

    1. Construído em JUnit
    2. Você recebe uma mensagem de exceção útil se o código no lambda não lançar uma exceção, e um stacktrace se lançar uma exceção diferente
    3. Conciso
    4. Permite que seus testes sigam Arrange-Act-Assert
    5. Você pode indicar com precisão qual código você está esperando para lançar a exceção
    6. Você não precisa listar a exceção esperada na cláusula throws
    7. Você pode usar a estrutura de asserção de sua escolha para fazer afirmações sobre a exceção capturada

    Um método semelhante será adicionado ao org.junit Assert no JUnit 4.13.

    Atualização: O JUnit5 possui uma melhoria no teste de exceções: assertThrows .

    O exemplo a seguir é de: Junit 5 User Guide

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

    Resposta original usando o JUnit 4.

    Existem várias maneiras de testar que uma exceção é lançada. Eu também tenho discutido as opções abaixo no meu post Como escrever grandes testes de unidade com JUnit

    Configure o 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!")); } } 

    Teste com a regra 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"); } 

    Você pode ler mais sobre o teste de exceções no wiki JUnit4 para testes de exceção e bad.robot – Expecting Exceptions JUnit Rule .

    Você também pode fazer isso:

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

    IMHO, a melhor maneira de verificar exceções no JUnit é o padrão 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()); } 

    O assertTrue pode ser um pouco forte para algumas pessoas, então assertThat(e.getMessage(), containsString("the message"); pode ser preferível.

    Solução JUnit 5

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

    Mais informações sobre o JUnit 5 em http://junit.org/junit5/docs/current/user-guide/#writing-tests-assertions

    Eu tentei muitos dos methods aqui, mas eles eram complicados ou não satisfazem meus requisitos. De fato, pode-se escrever um método auxiliar de forma bastante simples:

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

    Use assim:

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

    Zero dependencies: sem necessidade de mockito, sem necessidade de powermock; e funciona muito bem com as aulas finais.

    O JUnit tem suporte embutido para isso, com um atributo “esperado”

    Solução Java 8

    Se você gostaria de uma solução que:

    • Utiliza lambdas Java 8
    • Não depende de qualquer magia JUnit
    • Permite que você verifique várias exceções em um único método de teste
    • Verifica se uma exceção está sendo lançada por um conjunto específico de linhas dentro de seu método de teste, em vez de qualquer linha desconhecida em todo o método de teste
    • Gera o object de exceção real que foi lançado para que você possa examiná-lo

    Aqui está uma function de utilidade que eu escrevi:

     public final  T expectException( Class 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. } 

    ( retirado do meu blog )

    Use-o da seguinte maneira:

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

    No meu caso eu sempre recebo RuntimeException do db, mas as mensagens são diferentes. E exceção precisa ser tratada, respectivamente. Aqui está como eu testei:

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

    In JUnit 4 or later you can test the exceptions as follows

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

    this provides a lot of features which can be used to improve our JUnit tests.
    If you see the below example I am testing 3 things on the exception.

    1. The Type of exception thrown
    2. The exception Message
    3. The cause of the exception

     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.equalTo(exceptionCause)); classUnderTest.methodUnderTest("param1", "param2"); } } 

    We can use an assertion fail after the method that must return an exception:

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

    The most flexible and elegant answer for Junit 4 I found in the Mkyoung blog . It have the flexibility of the try/catch using the @Rule annotation. I liked this approach because I already needed to read specific attributes of a customized exception.

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

    Additionally to what NamShubWriter has said, make sure that:

    • The ExpectedException instance is public ( Related Question )
    • The ExpectedException isn’t instantiated in say, the @Before method. This post clearly explains all the intricacies of JUnit’s order of execution.

    Do not do this:

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

    Finally, this blog post clearly illustrates how to assert that a certain exception is thrown.

    Just make a Matcher that can be turned off and on, like this:

     public class ExceptionMatcher extends BaseMatcher { 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 usá-lo:

    add public ExpectedException exception = ExpectedException.none(); , then:

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

    Take for example, you want to write Junit for below mentioned code fragment

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

    The above code is to test for some unknown exception that may occur and the below one is to assert some exception with custom message.

      @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"}); } 

    With Java 8 you can create a method taking a code to check and expected exception as parameters:

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

    and then inside your test:

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

    Benefits:

    • not relying on any library
    • localised check – more precise and allows to have multiple assertions like this within one test if needed
    • easy to use

    My solution using Java 8 lambdas:

     public static  T assertThrows(Class 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 } } } 

    You have to define a FunctionalInterface, because Runnable doesn’t declare the required throws .

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

    The method can be used as follows:

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

    There are two ways of writing test case

    1. Annotate the test with the exception which is thrown by the method. Something like this @Test(expected = IndexOutOfBoundsException.class)
    2. You can simply catch the exception in the test class using the try catch block and assert on the message that is thrown from the method in test class.

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

    I hope this answers your query Happy learning…

    Junit4 solution with Java8 is to use this function:

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

    Usage is then:

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

    Note that the only limitation is to use a final object reference in lambda expression. This solution allows to continue test assertions instead of expecting thowable at method level using @Test(expected = IndexOutOfBoundsException.class) solution.

    I recomend library assertj-core to handle exception in junit test

    In java 8, like this:

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