2271

How can I use JUnit idiomatically to test that some code throws an exception?

While I can certainly do something like this:

@Test
public void testFooThrowsIndexOutOfBoundsException() {

    boolean thrown = false;

    try {
        foo.doStuff();
    } catch (IndexOutOfBoundsException e) {
        thrown = true;
    }

    assertTrue(thrown);
}

I recall that there is an annotation or an Assert.xyz or something that is far less kludgy and far more in-the-spirit of JUnit for these sorts of situations.

Arun Sudhakaran
  • 2,167
  • 4
  • 27
  • 52
SCdF
  • 57,260
  • 24
  • 77
  • 113
  • 27
    The problem with any other approach but this is that they invariably end the test once the exception has been thrown. I, on the other hand, often still want to call `org.mockito.Mockito.verify` with various parameters to make sure that certain things happened (such that a logger service was called with the correct parameters) before the exception was thrown. – ZeroOne Jan 17 '13 at 11:05
  • 5
    You can see how to exceptions test in JUnit wiki page https://github.com/junit-team/junit/wiki/Exception-testing – PhoneixS Feb 19 '14 at 11:46
  • 6
    @ZeroOne - For that I would have two different tests- one for the exception and one to verify interaction with your mock. – tddmonkey Dec 25 '14 at 17:01
  • There is a way to do this with JUnit 5, I have updated my answer below. – Dilini Rajapaksha May 02 '17 at 03:05
  • Here is a nice example on [how assert that an exception is Thrown](https://www.codingeek.com/tutorials/junit/assert-exception-thrown-junit/) it in JUnit4 and JUnit5 – Hitesh Garg Apr 12 '21 at 18:12

35 Answers35

2556

It depends on the JUnit version and what assert libraries you use.

The original answer for JUnit <= 4.12 was:

    @Test(expected = IndexOutOfBoundsException.class)
    public void testIndexOutOfBoundsException() {

        ArrayList emptyList = new ArrayList();
        Object o = emptyList.get(0);

    }

Though answer has more options for JUnit <= 4.12.

Reference:

2240
  • 1,547
  • 2
  • 12
  • 30
skaffman
  • 398,947
  • 96
  • 818
  • 769
  • 78
    This piece of code will not work if you expect an exception only somewhere in your code, and not a blanket like this one. – Oh Chin Boon Jun 27 '11 at 14:50
  • 5
    @skaffman This wouldn't work with org.junit.experimental.theories.Theory runned by org.junit.experimental.theories.Theories – Artem Oboturov Apr 27 '12 at 16:01
  • @skaffman: Is there a way to do similar thing in `junit 3.8`, expect method to throw exception? – Rachel Jun 08 '12 at 18:48
  • 85
    Roy Osherove discourages this kind of Exception testing in *The art of Unit Testing*, since the Exception might be anywhere inside the test and not only inside the unit under test. – Kevin Wittek Jan 22 '15 at 14:36
  • agree with @Kiview's point, this way might not actually test what you wanted to test. false positives are a pain. – sara Mar 22 '16 at 15:06
  • 23
    I disagree with @Kiview/Roy Osherove. In my view, tests should be for behaviour, not implementation. By testing that a specific method can throw an error, you are tying your tests directly to the implementation. I would argue that testing in the method shown above provides a more valuable test. The caveat I would add is that in this case I would test for a custom exception, so that I know I am getting the exception I really want. – nickbdyer May 03 '16 at 12:22
  • 2
    @nickbdyer Of course you want to test the behaviour. But do you want to test the behaviour of `ArrayList?` constructor or of the `get()` method? In the example above, you are testing both. The test would pass if your constructor would throw this exception, although you want to test the `get()` method. – Kevin Wittek May 03 '16 at 16:17
  • 6
    Neither. I want to test the behaviour of the class. What is important, is that if I try to retrieve something that isn't there, I get an exception. The fact that the data structure is `ArrayList` that responds to `get()` is irrelevant. If I chose in the future to move to a primitive array, I would then have to change this test implementation. The data structure should be hidden, so that the test can focus on the behaviour of the *class*. – nickbdyer May 03 '16 at 16:33
  • This question pops up in Google when you search for JUnit Exceptions. Can someone edit this answer and provide the info related to JUnit 4.7's features? http://stackoverflow.com/a/16725280/1199832 – Halley Nov 08 '16 at 12:28
  • @OhChinBoon You could make your own subclass of Exception or RuntimeException and catch that. And then make sure your subclass isn't being used in more than one place – Dylanthepiguy Mar 16 '17 at 21:47
  • 1
    public void testIndexOutOfBoundsException() throws IndexOutOfBoundsException { ... } should be added. – NoName Oct 16 '17 at 13:01
  • This works nice !.... but, it seems that when you use this sort of solutions, actually you are not doing the right thing with exceptions. Please read the [link](http://www.baeldung.com/exception-handling-for-rest-with-spring?utm_source=email&utm_medium=email&utm_campaign=series1-rest&tl_inbound=1&tl_target_all=1&tl_period_type=3) the *new solution3*. Errors and Exceptions should not interrupt the unit testing. – Juan Salvador Feb 09 '18 at 19:10
  • 1
    i think this way is legit as well, just a personal preference. but it is also nice to mention that this might "catch" all exceptions of that type within your test and sometimes it will be more accurate to catch the exception inside the test around a specific method call, where you expect the exception to occur. so if you keep that in mind, it's legit to write a test just like this – benez Feb 14 '18 at 10:45
  • 3
    @nickbdyer I think there's some miscommunication here. Kiview/Kevin Wittek is saying any method used in the test could throw the exception and cause the test to pass without reaching the statement that is actually supposed to throw an exception of that type. The data structure being used is irrelevant to his point. If the structure is wrapped inside a method of the class under test, you're right that it doesn't matter which statement inside that class is throwing the exception, but he wasn't contradicting that. – Vivek Chavda Jun 20 '18 at 17:50
1428

Edit: Now that JUnit 5 and JUnit 4.13 have been released, the best option would be to use Assertions.assertThrows() (for JUnit 5) and Assert.assertThrows() (for JUnit 4.13+). See my other answer for details.

If you haven't migrated to JUnit 5, but can use JUnit 4.7, you can use the ExpectedException Rule:

public class FooTest {
  @Rule
  public final ExpectedException exception = ExpectedException.none();

  @Test
  public void doStuffThrowsIndexOutOfBoundsException() {
    Foo foo = new Foo();

    exception.expect(IndexOutOfBoundsException.class);
    foo.doStuff();
  }
}

This is much better than @Test(expected=IndexOutOfBoundsException.class) because the test will fail if IndexOutOfBoundsException is thrown before foo.doStuff()

See this article for details.

t0r0X
  • 4,212
  • 1
  • 38
  • 34
NamshubWriter
  • 23,549
  • 2
  • 41
  • 59
  • 17
    @skaffman - If I've understood this correctly, it looks like the exception.expect is being applied only within one test, not the whole class. – bacar Jul 06 '12 at 11:41
  • 5
    If the exception we expect to be thrown is an checked exception, should we add throws or try-catch or test this situation in another way? – Mohammad Jafar Mashhadi Jun 29 '13 at 08:05
  • 1
    IMHO the answer from _rwoo_ below is a much better solution (http://code.google.com/p/catch-exception/) i.e. in this example when you `throw new NullPointerException();` after `foo.doStuff()` the test will **not** fail with an NPE. – TmTron Sep 27 '13 at 14:35
  • 5
    @MartinTrummer No code should run after foo.doStuff() since the exception is thrown and the method is exited. Having code after an expected exception (with the exception of closing resources in a finally) is unhelpful anyway since it should never be executed if the exception is thrown. – Jason Thompson Jan 17 '14 at 15:59
  • 1
    @Jason Thompson: "should" is nice, but not bullet-proof: With verify-exception you can be sure that the test is okay, even if someone else added some code after `doStuff()`: when the new code passes, so does the test and more importantly: when the new code throws, the test will fail. the given "solution" would hide this fact (and moreover verify-exception is more concise and thus less error-prone): – TmTron Jan 20 '14 at 09:32
  • 1
    @MartinTrummer What I'm struggling to understand is how code can execute after an exception is thrown. Perhaps you can give an example. My understanding is that as soon as an exception is thrown, the method exits with an exception. So if I had a function that looked like this: void myMethod { throw new IllegalStateException(); executeOtherMethod(); } As far as I know, there is no way executeOtherMethod() would ever be called. So it's a non issue. This code doesn't change how java works, but rather tells the test runner that the method will throw an exception and some characteristics of it. – Jason Thompson Jan 20 '14 at 14:51
  • 1
    @Jason but that's not the code you have. you have `foo.doStuff(); bar.doStuff();` - and you expect `foo.doStuff();` to throw. so if it does throw, `bar.doStuff()` is never executed (that's bad). but even worse is the case, when the code changes and `foo.doStuff()` does not throw anymore. now it's possible that `bar.doStuff()` throws insteead- the test passes - and you don't notice that the new code actually broke the original expectations that `foo.doStuff();` throws. – TmTron Jan 21 '14 at 06:14
  • @JasonThompson: usually in a testing environment the exception is swallowed and you assert it was thrown. The test doesn't exit in that case. – Tom Jun 20 '14 at 19:41
  • As I commented on rwoo's answer, I think the drawback with his library is that you can't proxy every object [for example classes that are final?]... but I'm not sure without trying it out. – Tom Jun 20 '14 at 19:42
  • 9
    This is the best approach. There are two advantages here, compared to skaffman's solution. Firstly, the `ExpectedException` class has ways of matching the exception's message, or even writing your own matcher that depends on the class of exception. Secondly, you can set your expectation immediately before the line of code that you expect to throw the exception - which means your test will fail if the wrong line of code throws the exception; whereas there's no way to do that with skaffman's solution. – Dawood ibn Kareem Jul 26 '14 at 10:58
  • Doesn't work when we extend TestCase, the test fails although the exception is thrown as expected – singe3 Aug 07 '14 at 08:17
  • 1
    @singe31 The OP asked about JUnit4, and JUnit4-style tests shouldn't extend TestCase – NamshubWriter Sep 21 '14 at 16:56
  • 1
    @DavidWallace the problem I with this approach is if you want to assert or check any behavior after the executed methods (like verify that any mock behavior did or did not occur) you cannot do it because your test will exit execution when the exception is throw. This can lead to unexpected test behavior if you have some `verify` after the method call that you believe is getting executed, but it actually isn't. – mkobit Nov 12 '14 at 23:31
  • @MikeKobit - So are you testing that the exception is thrown, or are you testing something else? I am a strong advocate of the "one test case, one assertion" approach - that is, if you're testing the throwing of the exception, there shouldn't be any other asserts or verifies occurring after the exception. – Dawood ibn Kareem Nov 12 '14 at 23:36
  • 1
    @DavidWallace I've had the case before where I want to test a method on a component that will throw an exception. I also want to make sure that a side effect has/has not happened. If I am using a mock framework like Mockito with the answer above, I wouldn't be able to verify any behavior. Example demoing sort of what I am talking about - http://stackoverflow.com/questions/13224288/mockito-verify-after-exception-junit-4-10 – mkobit Nov 13 '14 at 01:14
  • @MikeKobit OK, fair enough, that sounds reasonable. I imagine that would be a fairly rare kind of test case though. – Dawood ibn Kareem Nov 13 '14 at 01:52
  • It looks like Eclipse's coverage tool has trouble with this (not that that really matters) – Thomas Apr 01 '15 at 01:07
  • 5
    @MJafarMash if the exception you expect to throw is checked, then you would add that exception to the throws clause of the test method. You do the same any time you are testing a method that is declared to throw a checked exception, even if the exception isn't triggered in the particular test case. – NamshubWriter May 10 '15 at 14:38
  • @DavidWallace how does ExpectedException test for exception message? I dont see anything in the 4.12 API for that. – Ungeheuer Oct 27 '16 at 18:29
  • You can pass a Hamcrest Matcher to `expect` to analyse the exception. Or even easier - you can pass a `String` to `expectMessage` that you expect to be a substring of the message. http://junit.org/junit4/javadoc/4.12/org/junit/rules/ExpectedException.html – Dawood ibn Kareem Oct 27 '16 at 18:31
  • You can do it that way : `exception.expectMessage("foo bar");` – Marc Bouvier Apr 26 '18 at 08:52
  • How do you set an error message ofr the test if exception is not thrown? – dhalfageme Mar 21 '20 at 09:18
505

Be careful using expected exception, because it only asserts that the method threw that exception, not a particular line of code in the test.

I tend to use this for testing parameter validation, because such methods are usually very simple, but more complex tests might better be served with:

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

Apply judgement.

daveb
  • 74,111
  • 6
  • 45
  • 51
  • 110
    Maybe I'm old school but I still prefer this. It also gives me a place to test the exception itself: sometimes I have exceptions with getters for certain values, or I might simply look for a particular value in the message (e.g. looking for "xyz" in the message "unrecognized code 'xyz'"). – Rodney Gitzel Oct 06 '10 at 17:22
  • 3
    I think NamshubWriter's approach gives you the best of both worlds. – Eddie Mar 09 '11 at 19:21
  • +1 useful in some scenarios where expected = xx doesn't match requirements. – Oh Chin Boon Jun 27 '11 at 15:20
  • 4
    Using ExpectedException you could call N exception.expect per method to test like this exception.expect(IndexOutOfBoundsException.class); foo.doStuff1(); exception.expect(IndexOutOfBoundsException.class); foo.doStuff2(); exception.expect(IndexOutOfBoundsException.class); foo.doStuff3(); – user1154664 Oct 09 '12 at 17:07
  • 10
    @user1154664 Actually, you can't. Using ExpectedException you can only test that one method throws an exception, because when that method is called, the test will stop executing because it threw the expected exception! – NamshubWriter Feb 24 '14 at 16:26
  • 2
    Your first sentence just isn't true. When using `ExpectedException`, the normal thing to do is to set the expectation immediately before the line that you expect to throw the exception. That way, if an earlier line throws the exception, it won't trigger the rule, and the test will fail. – Dawood ibn Kareem Jul 26 '14 at 10:53
  • This was apt for my case. I wanted to check state of some objects after the exception was thrown which could not be done with 'expected' as it just exists after exception is thrown. – Anmol Gupta Oct 12 '15 at 18:15
  • And also this is compatible with Arquillian-Tests. I tried this with @Rule Annotation but got Initialization Error with Arquillian. – Arthur Welsch Aug 23 '16 at 08:10
  • Furthermore, with this approach, we could add more assertions in the exception handling for state checks if necessary – Bertie Jul 01 '17 at 11:31
  • I agree, `ExpectedException` rule is not suitable for every situation. – Marc Bouvier Apr 26 '18 at 08:54
  • Still using this in 2019. Makes it easy for me to run other verification code after the (otherwise execution-ending-) exception is thrown. – ebwb May 02 '19 at 13:44
  • Problem with that approach is code coverage will never pick up that line of code – JohnnyB Nov 09 '20 at 19:55
  • i have a method execute() which throws checked IOException, going with above approach, catch block didn't catch IOException. – SudhirKumar Nov 04 '21 at 00:02
  • Nice. But we also want to `fail()` when the wrong exception is thrown, which can easily be tested by adding a `catch (Exception e)` handler. – Arthur Nov 28 '22 at 23:36
235

in junit, there are four ways to test exception.

junit5.x

  • for junit5.x, you can use assertThrows as following

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

junit4.x

  • for junit4.x, use the optional 'expected' attribute of Test annonation

    @Test(expected = IndexOutOfBoundsException.class)
    public void testFooThrowsIndexOutOfBoundsException() {
        foo.doStuff();
    }
    
  • for junit4.x, use the ExpectedException rule

    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();
        }
    }
    
  • you also can use the classic try/catch way widely used under 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.
        }
    }
    
  • so

    • if you like junit 5, then you should like the 1st one
    • the 2nd way is used when you only want test the type of exception
    • the first and last two are used when you want test exception message further
    • if you use junit 3, then the 4th one is preferred
  • for more info, you can read this document and junit5 user guide for details.

Yassin Hajaj
  • 21,337
  • 9
  • 51
  • 89
walsh
  • 3,041
  • 2
  • 16
  • 31
  • 11
    For me this is the best answer, it covers all the ways very clearly, thanks ! Personally I continue using the 3rd option even with Junit4 for readability, to avoid empty catch block you can also catch Throwable and assert type of e – Nicolas Cornette Jun 16 '16 at 08:57
  • Is it possible to use ExpectedException to expect checked exception? – miuser Mar 02 '17 at 09:23
  • All it is is an accumulation of the top three answers. IMO, this answer shouldn't even have been posted if it is not adding nothing new. Just answering (a popular question) for the rep. Pretty useless. – Paul Samsotha May 05 '18 at 01:27
  • sure, because you can pass any type derived from `Trowable` to the method `ExpectedException.expect`. please see [it's signature](https://junit.org/junit4/javadoc/4.12/org/junit/rules/ExpectedException.html#expect(java.lang.Class)). @miuser – walsh Jun 08 '18 at 13:47
  • This is the best answer – avijendr Jul 03 '20 at 18:45
  • 2
    I would point out that Junit 4.13 (emphasis on the ".13")...supports assertThrows. I am upvoting, because this is a good "complete overview" answer, but I hope you will consider a 4.13 caveat. – granadaCoder Jan 19 '21 at 17:18
  • `org.junit.rules.ExpectedException#none` is marked as deprecated since 4.13. org.junit.Assert#assertThrows can be used – Saif Aug 20 '22 at 22:25
223

As answered before, there are many ways of dealing with exceptions in JUnit. But with Java 8 there is another one: using Lambda Expressions. With Lambda Expressions we can achieve a syntax like this:

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

assertThrown accepts a functional interface, whose instances can be created with lambda expressions, method references, or constructor references. assertThrown accepting that interface will expect and be ready to handle an exception.

This is relatively simple yet powerful technique.

Have a look at this blog post describing this technique: http://blog.codeleak.pl/2014/07/junit-testing-exception-with-java-8-and-lambda-expressions.html

The source code can be found here: https://github.com/kolorobot/unit-testing-demo/tree/master/src/test/java/com/github/kolorobot/exceptions/java8

Disclosure: I am the author of the blog and the project.

xehpuk
  • 7,814
  • 3
  • 30
  • 54
Rafal Borowiec
  • 5,124
  • 1
  • 24
  • 20
  • 2
    I like this solution but can I download this from a maven repo? – Selwyn Mar 31 '15 at 02:07
  • @Airduster one implementation of this idea that's available on Maven is http://stefanbirkner.github.io/vallado/ – NamshubWriter May 10 '15 at 14:35
  • 6
    @CristianoFontes a simpler version of this API is slated for JUnit 4.13. See https://github.com/junit-team/junit/commit/bdb1799a6b58c4ab40c418111333f4e8e1816e7e – NamshubWriter Jul 21 '15 at 02:18
  • @RafalBorowiec technically, `new DummyService()::someMethod` is a `MethodHandle`, but this approach works equally well with lambda expressions. – Andy Apr 28 '17 at 19:48
  • @NamshubWriter, it seems that junit 4.13 was abandoned in favor of junit 5: https://stackoverflow.com/questions/156503/how-do-you-assert-that-a-certain-exception-is-thrown-in-junit-4-tests/46514550#46514550 – Vadzim Dec 19 '17 at 11:02
  • @Vadzim JUnit 4.13 is not abandoned. The team realizes that some people cannot migrate to JUnit 5 and 4.13 has some nice fixes, but most of the recent efforts have been focused on the 5.x code base. – NamshubWriter Dec 19 '17 at 15:45
  • Junit 4.13 is out, also a version of this also exists with assertJ and google-truth, as indicated by other answers here. – tkruse Mar 03 '20 at 04:29
137

tl;dr

  • post-JDK8 : Use AssertJ or custom lambdas to assert exceptional behaviour.

  • pre-JDK8 : I will recommend the old good try-catch block. (Don't forget to add a fail() assertion before the catch block)

Regardless of Junit 4 or JUnit 5.

the long story

It is possible to write yourself a do it yourself try-catch block or use the JUnit tools (@Test(expected = ...) or the @Rule ExpectedException JUnit rule feature).

But these ways are not so elegant and don't mix well readability wise with other tools. Moreover, JUnit tooling does have some pitfalls.

  1. The try-catch block you have to write the block around the tested behavior and write the assertion in the catch block, that may be fine but many find that this style interrupts the reading flow of a test. Also, you need to write an Assert.fail at the end of the try block. Otherwise, the test may miss one side of the assertions; PMD, findbugs or Sonar will spot such issues.

  2. The @Test(expected = ...) feature is interesting as you can write less code and then writing this test is supposedly less prone to coding errors. But this approach is lacking in some areas.

    • If the test needs to check additional things on the exception like the cause or the message (good exception messages are really important, having a precise exception type may not be enough).
    • Also as the expectation is placed around in the method, depending on how the tested code is written then the wrong part of the test code can throw the exception, leading to false-positive test and I'm not sure that PMD, findbugs or Sonar will give hints on such code.

      @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. The ExpectedException rule is also an attempt to fix the previous caveats, but it feels a bit awkward to use as it uses an expectation style, EasyMock users know very well this style. It might be convenient for some, but if you follow Behaviour Driven Development (BDD) or Arrange Act Assert (AAA) principles the ExpectedException rule won't fit in those writing style. Aside from that it may suffer from the same issue as the @Test way, depending on where you place the expectation.

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

    Even the expected exception is placed before the test statement, it breaks your reading flow if the tests follow BDD or AAA.

    Also, see this comment issue on JUnit of the author of ExpectedException. JUnit 4.13-beta-2 even deprecates this mechanism:

    Pull request #1519: Deprecate ExpectedException

    The method Assert.assertThrows provides a nicer way for verifying exceptions. In addition, the use of ExpectedException is error-prone when used with other rules like TestWatcher because the order of rules is important in that case.

So these above options have all their load of caveats, and clearly not immune to coder errors.

  1. There's a project I became aware of after creating this answer that looks promising, it's catch-exception.

    As the description of the project says, it let a coder write in a fluent line of code catching the exception and offer this exception for the latter assertion. And you can use any assertion library like Hamcrest or AssertJ.

    A rapid example taken from the 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();
    

    As you can see the code is really straightforward, you catch the exception on a specific line, the then API is an alias that will use AssertJ APIs (similar to using assertThat(ex).hasNoCause()...). At some point the project relied on FEST-Assert the ancestor of AssertJ. EDIT: It seems the project is brewing a Java 8 Lambdas support.

    Currently, this library has two shortcomings :

    • At the time of this writing, it is noteworthy to say this library is based on Mockito 1.x as it creates a mock of the tested object behind the scene. As Mockito is still not updated this library cannot work with final classes or final methods. And even if it was based on Mockito 2 in the current version, this would require to declare a global mock maker (inline-mock-maker), something that may not what you want, as this mock maker has different drawbacks that the regular mock maker.

    • It requires yet another test dependency.

    These issues won't apply once the library supports lambdas. However, the functionality will be duplicated by the AssertJ toolset.

    Taking all into account if you don't want to use the catch-exception tool, I will recommend the old good way of the try-catch block, at least up to the JDK7. And for JDK 8 users you might prefer to use AssertJ as it offers may more than just asserting exceptions.

  2. With the JDK8, lambdas enter the test scene, and they have proved to be an interesting way to assert exceptional behaviour. AssertJ has been updated to provide a nice fluent API to assert exceptional behaviour.

    And a sample test with 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. With a near-complete rewrite of JUnit 5, assertions have been improved a bit, they may prove interesting as an out of the box way to assert properly exception. But really the assertion API is still a bit poor, there's nothing outside assertThrows.

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

    As you noticed assertEquals is still returning void, and as such doesn't allow chaining assertions like AssertJ.

    Also if you remember name clash with Matcher or Assert, be prepared to meet the same clash with Assertions.

I'd like to conclude that today (2017-03-03) AssertJ's ease of use, discoverable API, the rapid pace of development and as a de facto test dependency is the best solution with JDK8 regardless of the test framework (JUnit or not), prior JDKs should instead rely on try-catch blocks even if they feel clunky.

This answer has been copied from another question that don't have the same visibility, I am the same author.

Denis Stafichuk
  • 2,415
  • 2
  • 16
  • 29
bric3
  • 40,072
  • 9
  • 91
  • 111
  • 1
    Adding org.junit.jupiter:junit-jupiter-engine:5.0.0-RC2 dependency (in addition to the already existing junit:junit:4.12) to be able to use assertThrows is perhaps not the preferred solution, but did not cause any issues for me. – anre Aug 03 '17 at 12:13
  • I'm a fan of using the ExpectedException rule but it always bothered me that it breaks with AAA. You've wrote an excellent article to describe all the different approaches and you've definitely encouraged me to try AssertJ :-) Thanks! – BitfulByte Jul 06 '18 at 06:34
  • @PimHazebroek thanks. AssertJ API is quite rich. Better in my opinion that what JUnit proposes out of the box. – bric3 Jul 06 '18 at 07:54
90

Now that JUnit 5 and JUnit 4.13 have been released, the best option would be to use Assertions.assertThrows() (for JUnit 5) and Assert.assertThrows() (for JUnit 4.13). See the JUnit 5 User Guide.

Here is an example that verifies an exception is thrown, and uses Truth to make assertions on the exception message:

public class FooTest {
  @Test
  public void doStuffThrowsIndexOutOfBoundsException() {
    Foo foo = new Foo();

    IndexOutOfBoundsException e = assertThrows(
        IndexOutOfBoundsException.class, foo::doStuff);

    assertThat(e).hasMessageThat().contains("woops!");
  }
}

The advantages over the approaches in the other answers are:

  1. Built into JUnit
  2. You get a useful exception message if the code in the lambda doesn't throw an exception, and a stacktrace if it throws a different exception
  3. Concise
  4. Allows your tests to follow Arrange-Act-Assert
  5. You can precisely indicate what code you are expecting to throw the exception
  6. You don't need to list the expected exception in the throws clause
  7. You can use the assertion framework of your choice to make assertions about the caught exception
NamshubWriter
  • 23,549
  • 2
  • 41
  • 59
  • This approach is clean, but I don't see how this allows our test to follow "Arrange-Act-Assert", since we have to wrap the "Act" part in an "assertThrow", which is an assert. – Clockwork Mar 08 '19 at 15:19
  • @Clockwork The lambda is the "act". The goal of Arrange-Act-Assert is to make the code clean and simple (and therefore easy to understand and maintain). As you stated, this approach is clean. – NamshubWriter Mar 11 '19 at 17:10
  • I was still hoping I could assert the throw and the exception on the end of the test though, in the "assert" part. In this approach, you need to wrap the act in a first assert to catch it first. – Clockwork Mar 11 '19 at 18:02
  • That would require more code in every test to do the assertion. That's more code and would be error-prone. – NamshubWriter Mar 11 '19 at 18:36
54

Update: JUnit5 has an improvement for exceptions testing: assertThrows.

The following example is from: Junit 5 User Guide

import static org.junit.jupiter.api.Assertions.assertThrows;

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

Original answer using JUnit 4.

There are several ways to test that an exception is thrown. I have also discussed the below options in my post How to write great unit tests with JUnit

Set the expected parameter @Test(expected = FileNotFoundException.class).

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

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

Testing with ExpectedException Rule.

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

You could read more about exceptions testing in JUnit4 wiki for Exception testing and bad.robot - Expecting Exceptions JUnit Rule.

Sridhar Sarnobat
  • 25,183
  • 12
  • 93
  • 106
Dilini Rajapaksha
  • 2,610
  • 4
  • 30
  • 41
46

How about this: catch a very general exception, make sure it makes it out of the catch block, then assert that the class of the exception is what you expect it to be. This assert will fail if a) the exception is of the wrong type (eg. if you got a Null Pointer instead) and b) the exception wasn't ever thrown.

public void testFooThrowsIndexOutOfBoundsException() {
  Throwable e = null;

  try {
    foo.doStuff();
  } catch (Throwable ex) {
    e = ex;
  }

  assertTrue(e instanceof IndexOutOfBoundsException);
}
Unmitigated
  • 76,500
  • 11
  • 62
  • 80
Johan
  • 1,940
  • 1
  • 13
  • 18
  • 4
    Also, you won't see what kind of Exception ex is in the test results when the day comes where the test fails. – jontejj Mar 14 '13 at 16:13
  • 1
    This can be improved a bit by changing how you assert at the end. `assertEquals(ExpectedException.class, e.getClass())` will show you the expected and actual values when the test fails. – Cypher Nov 15 '18 at 00:54
42

Using an AssertJ assertion, which can be used alongside JUnit:

import static org.assertj.core.api.Assertions.*;

@Test
public void testFooThrowsIndexOutOfBoundsException() {
  Foo foo = new Foo();

  assertThatThrownBy(() -> foo.doStuff())
        .isInstanceOf(IndexOutOfBoundsException.class);
}

It's better than @Test(expected=IndexOutOfBoundsException.class) because it guarantees the expected line in the test threw the exception and lets you check more details about the exception, such as message, easier:

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

Maven/Gradle instructions here.

weston
  • 54,145
  • 21
  • 145
  • 203
  • most concise way and nobody appreciates it, strange.. I only have one problem with the assertJ library, assertThat conflicts name-wise with junit's. more about assertJ throwby: [JUnit: Testing Exceptions with Java 8 and AssertJ 3.0.0 ~ Codeleak.pl](http://blog.codeleak.pl/2015/04/junit-testing-exceptions-with-java-8.html) – ycomp Mar 21 '16 at 20:03
  • @ycomp Well it is a new answer on a very old question, so the score difference is deceptive. – weston Mar 24 '16 at 08:46
  • That's probably the best solution if one can use Java 8 and AssertJ ! – Pierre Henry Mar 25 '16 at 15:01
  • @ycomp I suspect this name conflict may be by design: the AssertJ library therefore strongly encourages you never to use the JUnit `assertThat`, always the AssertJ one. Also the JUnit method returns only a "regular" type, whereas the AssertJ method returns an `AbstractAssert` subclass ... allowing stringing of methods as above (or whatever the technical terms is for this...). – mike rodent Oct 11 '16 at 16:13
  • @weston actually I've just used your technique in AssertJ 2.0.0. No excuse for not upgrading, no doubt, but though you might like to know. – mike rodent Oct 11 '16 at 16:14
  • @mikerodent _"allowing stringing of methods as above (or whatever the technical terms is for this...)"_ fluent would be the term. So, _"... allowing fluent statements."_ – weston Oct 11 '16 at 18:20
  • @mikerodent that is interesting that it works in 2, I don't know why I thought was 3 – weston Oct 11 '16 at 18:21
39

BDD Style Solution: JUnit 4 + Catch Exception + AssertJ

import static com.googlecode.catchexception.apis.BDDCatchException.*;

@Test
public void testFooThrowsIndexOutOfBoundsException() {

    when(() -> foo.doStuff());

    then(caughtException()).isInstanceOf(IndexOutOfBoundsException.class);

}

Dependencies

eu.codearte.catch-exception:catch-exception:2.0
MariuszS
  • 30,646
  • 12
  • 114
  • 155
33

To solve the same problem I did set up a small project: http://code.google.com/p/catch-exception/

Using this little helper you would write

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

This is less verbose than the ExpectedException rule of JUnit 4.7. In comparison to the solution provided by skaffman, you can specify in which line of code you expect the exception. I hope this helps.

rwitzel
  • 1,694
  • 17
  • 21
  • I thought about doing something like this as well, but ultimately discovered that the true power of ExpectedException is that not only can you specify the expected exception, but you can also specify certain properties of the exception such as the expected cause or expected message. – Jason Thompson Jan 17 '14 at 16:28
  • My guess is that this solution has some of the same drawbacks as mocks? For example, if `foo` is `final` it will fail because you can't proxy `foo`? – Tom Jun 20 '14 at 19:39
  • Tom, if doStuff() is part of an interface the proxy approach will work. Otherwise this approach will fail, you are right. – rwitzel Jan 16 '15 at 09:49
22

You can also do this:

@Test
public void testFooThrowsIndexOutOfBoundsException() {
    try {
        foo.doStuff();
        assert false;
    } catch (IndexOutOfBoundsException e) {
        assert true;
    }
}
Dawood ibn Kareem
  • 77,785
  • 15
  • 98
  • 110
John Mikic
  • 640
  • 6
  • 11
  • 12
    In JUnit tests, it's better to use `Assert.fail()`, not `assert`, just in case your tests run in an environment where assertions are not enabled. – NamshubWriter Jan 14 '15 at 04:51
15

IMHO, the best way to check for exceptions in JUnit is the try/catch/fail/assert pattern:

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

The assertTrue might be a bit strong for some people, so assertThat(e.getMessage(), containsString("the message"); might be preferable.

Gerold Broser
  • 14,080
  • 5
  • 48
  • 107
Alex Collins
  • 980
  • 11
  • 23
14

JUnit 5 Solution

import static org.junit.jupiter.api.Assertions.assertThrows;

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

More Infos about JUnit 5 on http://junit.org/junit5/docs/current/user-guide/#writing-tests-assertions

Sridhar Sarnobat
  • 25,183
  • 12
  • 93
  • 106
Daniel Käfer
  • 4,458
  • 3
  • 32
  • 41
  • [`expectThrows()`](https://javadoc.jitpack.io/com/github/cbeust/testng/master/javadoc/org/testng/Assert.html#expectThrows-java.lang.Class-org.testng.Assert.ThrowingRunnable-) is a part TestNG, not a JUnit – Ilya Serbis May 12 '20 at 21:35
13

The most flexible and elegant answer for Junit 4 I found in the Mkyong blog. It has the flexibility of the try/catch using the @Rule annotation. I like this approach because you can 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("");

    }

}
Dherik
  • 17,757
  • 11
  • 115
  • 164
12

I tried many of the methods here, but they were either complicated or didn't quite meet my requirements. In fact, one can write a helper method quite simply:

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 it like this:

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

Zero dependencies: no need for mockito, no need powermock; and works just fine with final classes.

Hugh Perkins
  • 7,975
  • 7
  • 63
  • 71
  • Interesting, but doesn't fit to AAA (Arrange Act Assert), where you want to do the Act and the Assert step in actually different steps. – grackkle Oct 28 '14 at 21:15
  • 1
    @bln-tom Technically it is two different steps, they're just not in that order. ;p – Hakanai Feb 02 '15 at 03:52
12

JUnit has built-in support for this, with an "expected" attribute.

Unmitigated
  • 76,500
  • 11
  • 62
  • 80
Mark Bessey
  • 19,598
  • 4
  • 47
  • 69
10

Java 8 solution

If you would like a solution which:

  • Utilizes Java 8 lambdas
  • Does not depend on any JUnit magic
  • Allows you to check for multiple exceptions within a single test method
  • Checks for an exception being thrown by a specific set of lines within your test method instead of any unknown line in the entire test method
  • Yields the actual exception object that was thrown so that you can further examine it

Here is a utility function that I wrote:

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 testing for "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.
}

(taken from my blog)

Use it as follows:

@Test
public void testMyFunction()
{
    RuntimeException e = expectException( RuntimeException.class, () -> 
        {
            myFunction();
        } );
    assert e.getMessage().equals( "I haz fail!" );
}

public void myFunction()
{
    throw new RuntimeException( "I haz fail!" );
}
Mike Nakis
  • 56,297
  • 11
  • 110
  • 142
9

In my case I always get RuntimeException from db, but messages differ. And exception need to be handled respectively. Here is how I tested it:

@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));
}
Macchiatow
  • 607
  • 10
  • 24
6

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

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

To use it:

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

ExceptionMatcher exMatch = new ExceptionMatcher(MyException.class);
exception.expect(exMatch);
someObject.somethingThatThrowsMyException();
exMatch.off();
evandrix
  • 6,041
  • 4
  • 27
  • 38
Tor P
  • 1,351
  • 11
  • 9
6

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());
}
Shessuky
  • 1,846
  • 21
  • 24
6

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.<Throwable>equalTo(exceptionCause));

        classUnderTest.methodUnderTest("param1", "param2");
    }

}
Jobin
  • 5,610
  • 5
  • 38
  • 53
5

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.

Community
  • 1
  • 1
Srini
  • 1,626
  • 2
  • 15
  • 25
4

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.

Donatello
  • 3,486
  • 3
  • 32
  • 38
4

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(".......);
Piotr Rogowski
  • 3,642
  • 19
  • 24
3

JUnit framework has assertThrows() method:

ArithmeticException exception = assertThrows(ArithmeticException.class, () ->
    calculator.divide(1, 0));
assertEquals("/ by zero", exception.getMessage());
Ilya Serbis
  • 21,149
  • 6
  • 87
  • 74
1

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"});
}
Shirsh Sinha
  • 156
  • 2
  • 8
1

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
fahrenx
  • 31
  • 3
1
    @Test(expectedException=IndexOutOfBoundsException.class) 
    public void  testFooThrowsIndexOutOfBoundsException() throws Exception {
         doThrow(IndexOutOfBoundsException.class).when(foo).doStuff();  
         try {
             foo.doStuff(); 
            } catch (IndexOutOfBoundsException e) {
                       assertEquals(IndexOutOfBoundsException .class, ex.getCause().getClass());
                      throw e;

               }

    }

Here is another way to check method thrown correct exception or not.

MangduYogii
  • 935
  • 10
  • 24
0

My solution using 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
        }
    }
}

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);
heio
  • 11
  • 3
0

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...

Sandeep Sukhija
  • 1,156
  • 16
  • 30
0

I would use assertThatThrownBy

@Test
public void testFooThrowsIndexOutOfBoundsException() {
  assertThatThrownBy(() -> doStuff()).isInstanceOf(IndexOutOfBoundsException.class)
}

Requires AssertJ - documentation references:

ryanwebjackson
  • 1,017
  • 6
  • 22
  • 36
mahb
  • 39
  • 6
-1

I wanted to comment with my solution to this problem, which avoided needing any of the exception related JUnit code.

I used assertTrue(boolean) combined with try/catch to look for my expected exception to be thrown. Here's an example:

public void testConstructor() {
    boolean expectedExceptionThrown;
    try {
        // Call constructor with bad arguments
        double a = 1;
        double b = 2;
        double c = a + b; // In my example, this is an invalid option for c
        new Triangle(a, b, c);
        expectedExceptionThrown = false; // because it successfully constructed the object
    }
    catch(IllegalArgumentException e) {
        expectedExceptionThrown = true; // because I'm in this catch block
    }
    catch(Exception e) {
        expectedExceptionThrown = false; // because it threw an exception but not the one expected
    }
    assertTrue(expectedExceptionThrown);
}
Matt Welke
  • 1,441
  • 1
  • 15
  • 40
-4
try {
    my method();
    fail( "This method must thrwo" );
} catch (Exception ex) {
    assertThat(ex.getMessage()).isEqual(myErrormsg);
}
Houssam Badri
  • 2,441
  • 3
  • 29
  • 60
  • 4
    You are answering on a 10 year old question, please expand your answer, why you think it provides something new, that the accepted answer does not cover. Also always try to tell something about your code and provide documentation or explanation. – hellow Aug 08 '18 at 11:24
  • 1
    This is basically a duplicate of [this 10 year old answer](https://stackoverflow.com/a/156868/2513200) (except for the check for the error message). – Hulk Aug 08 '18 at 12:07
  • I don't know why to downvote. There is no duplication. Please have a look at the check of the error msg. This is the right answer that I used today with my team @hellow – Houssam Badri Aug 08 '18 at 16:23
  • 1
    It's not always the same person who complains about your question/answer and downvots you (like in this case, I didn't, but please take my words and expand your answer). – hellow Aug 08 '18 at 19:47
  • 2
    I am not sure if the test depending just on the error message is a good practice. – Nithin Aug 09 '18 at 09:15
  • 1
    Yeah it is a good practice and useful when you have many error messages, so that you make sure that this specific one will be thrown (many possible exceptions) – Houssam Badri Aug 09 '18 at 10:00
  • 1
    Please what do you mean by expand answer Hebrow, this answer is for the question, so if you understand well the question and the code on it so the answer will be straightforward, he is needing just some code – Houssam Badri Aug 09 '18 at 10:01