This post has been migrated to http://www.thinkcode.se/blog/2015/11/20/expected-exceptions
Sometimes you want to verify that an exception is thrown in your code.
Let me show you three different ways to verify that the expected exception has been thrown.
The bullet proof approach
One solution that always works would be the one below:
You execute the action the test should check and catches a specific exception. And then check that the expected message actually is the message you see.
What is the problem then? The only issue I can think of is that it is unnecessary verbose. I am not comfortable with test code that isn’t straight through. In this case, there is a catch clause. In other cases there may be loops or even worse, conditions.
So to me, this works but it isn’t pretty.
Annotate the test
An approach that I often use is to annotate the test with the expected exception. It can look like this:
This is smaller. And smaller is good. But it is also a bit blunt. You will get feedback from the test when the expected exception isn’t thrown. But you will not get feedback if the message is something different from what you expected.
Given these two options, I usually prefer the last one. Even when I am not able to verify the message. The compactness of the code is appealing.
If I were able to use an annotation like
@Test(expected = RuntimeException.class, messgae = "Oops!") then that would have been a very nice solution. But JUnit doesn’t support that.
There is a third way to do this. That is to use a JUnit
@Rule annotation with
ExpectedException. Let me show you how.
You need to define a JUnit rule. And use it. It can be done like this:
This rule says that I don’t expect any exceptions to be thrown from my method. This means that the behaviour is consistent with the default behaviour of JUnit.
I can, however, define that an exception should be thrown in a test and define the class for the exception. This is what I do in
should_also_throw_runtime_exception(). And all of a sudden, I am not only able to assert the class for the thrown exception, I am also able to assert the message that was thrown. And I am able to do it in a test method where I don’t have any blocks.
I think it would have been nice to extend the test annotation to handle both exception and its message, but using this rule construction is almost just as good as an extended annotation. I am able to verify more things, using the field
thrown in this example, so I guess it is a resonable limitation.
Complete source code
I don’t like blog posts that hides stuff from me. Especially imports in example code. It makes the examples magic and I am not impressed by magic. The complete source code I used for this blog is therefore included below.
I would like to thank Malin Ekholm for proof reading.