0

I'm writing a JUnit/Mockito test where an exception is expected to be thrown. Of course I can just do this:

@Test(expected=IllegalArgumentException.class) 

But it doesn't let me to do anything else after it was thrown. So I was thinking maybe something more like:

Exception actualEx = null; try { // Act sut.doStuff(); } catch (final Exception ex) { actualEx = ex; } // Assert assertTrue(IllegalArgumentException.class.equals(actualEx.getClass())); // ... perhaps verify the exception details verifyNoMoreInteractions(mockObject); 

This seems pretty ugly and feels like it could be improved - is there a better way?

5
  • 3
    Have you tried the ExpectedException rule? alexruiz.developerblogs.com/?p=1530 Commented Nov 19, 2013 at 8:56
  • or catch-exception, too bad however they use FEST-Assert (almost dead) instead of AssertJ Commented Nov 19, 2013 at 9:30
  • @Brice Thanks but would prefer to avoid add-on libraries if I can help it... Commented Nov 19, 2013 at 9:41
  • I understand (I'm still not a fan of adding Nth libraries), though catch-exception is enable us to follow Arrange/Act/Assert or BDD principles in test which is more interesting regarding the readability of the test. Commented Nov 19, 2013 at 20:43
  • An alternative duplicate with answers that also cover JUnit5's AssertThrows: How do you assert that a certain exception is thrown in JUnit 4 tests? Commented Sep 18, 2019 at 10:34

3 Answers 3

2

I think you should be consistent throughout your project - although there are three or four different ways to solve this problem, you absolutely should not try to use all of them.

Since the ExpectedException mechanism is the most powerful and most versatile way, I would recommend you learn to use it. Its advantages include the following.

  • It's easy to check both the type of the thrown exception and its message.
  • You can do more sophisticated matching on the exception if you need to.
  • You can check exactly which line of your test throws the exception, by placing the expect call immediately before the line that you expect to throw the exception.

At the risk of sounding like a shampoo advertisement - now that I've used ExpectedException, I wouldn't use anything else!

Sign up to request clarification or add additional context in comments.

Comments

1

There is no best way. It depends :-) Take a look at the JUnit Wiki: https://github.com/junit-team/junit/wiki/Exception-testing

Comments

1

Just an add-on here. I agree with Stefan's post and that is a good resources. Here are the guidelines I follow.

  1. I only use the @Test(expected=...) if there is only one method call in the test and that is the method under test. That is because of the following... what if you have @Test(expect=NullPointerException.class) and you have a bug somewhere in the setup of the test that throws this exception. The test will pass having never called the method under test.

  2. So, in all other cases I use the ExpectedException Rule with the expect immediately before the call to the method under test. In this way if an exception is thrown in the code prior to the method call the test will fail.

I never use the catch / fail mechanism because it is too easy for someone inexperienced to remove the fail and this would allow the test to pass erroneously. If I need to do extra verification I still use ExpectedException and rethrow the exception inside the catch block after I have done any additional verification.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.