The above approach is a common pattern. The test will fail when no exception is thrown and the exception itself is verified in a catch clause (in the above example I used the FEST Fluent Assertions) and although it is perfectly fine I prefer the approach with ExpectedException rule.

With JUnit rule

The same example can be created using ExceptedException rule. The rule must be a public field marked with @Rule annotation. Please note that the "thrown" rule may be reused in many tests.

In general, I find the above code more readable hence I use this approach in my projects.

When the exception isn't thrown you will get the following message: java.lang.AssertionError: Expected test to throw (an instance of java.lang.IllegalArgumentException and exception with message "negatives not allowed: [-1, -2]"). Pretty nice.

But not all exceptions I check with the above approach. Sometimes I need to check only the type of the exception thrown and then I use @Test annotation.

With annotation

When the exception wasn't thrown you will get the following message: java.lang.AssertionError: Expected exception: java.lang.IllegalArgumentException

With this approach you need to be careful though. Sometimes it is tempting to expect general Exception, RuntimeException or even a Throwable. And this is considered as a bad practice, because your code may throw exception in other place than you actually expected and your test will still pass!

To sum up, in my code I use two approaches: with JUnit rule and with annotation. The advantages are:

Error messages when the code does not throw an exception are automagically handled

The readability is improved

There is less code to be created

catch-exceptions

In short, catch-exception is a library that catches exceptions in a single line of code and makes them available for further analysis.

Lambda expressions

As of Java 8 we have another way of dealing with exceptions: with lambda expressions, that make catch-exception library redundant. With just couple of lines of code, one can build quite cool code helping us in testing exceptions in JUnit without any additional library. See: Yet another way to handle exceptions in JUnit: catch-exception