You've written Java code that intentionally throws a specific exception under certain conditions. Now you need to write a JUnit test to make sure that the exception gets thrown.

But how do you do it?

Well, you could put your test case in a try/catch block. And I've been there. And done that.

But there's a better way. A cleaner way. A more joyful way.

Do it with the assertThrows() method.

Let me show you how.

An Example

Here's some code that throws a specific type of exception in the event of an unforeseen problem:

public void createEmailCode(Registrant registrant) {
    try {
        String code = createCode(registrant.getUsername(), RegistrantAuthentication.Type.EMAIL);

        String validationBody = "\n\nYour verification code for Carey Development, LLC and the CarEcosystem Network.\n\n"
                + "Use verification code: " + code;

        emailService.sendSimpleMessage(registrant.getEmailAddress(), "Your Verification Code", validationBody);
    } catch (Exception e) {
        LOG.error("Problem creating email code!", e);
        throw new EmailCodeCreateFailedException(e.getMessage());

That's a method that sends an email verification code to people who've just registered with the application. The user will check email for the code and enter it on the UI.

But something could go wrong with that whole process. In that event, the method catches any Exception and throws a RuntimeException instance called EmailCodeCreateFailedException.

Now let's say I want to test that block of code above to make sure it throws EmailCodeCreateFailedException in the event that any other exception gets thrown during the whole process.

In fact, I do want to test that. But how?

Enter assertThrows().


So what's this assertThrows() thing all about?

Well you're probably familiar with assertEquals(). If not, you're way to new to JUnit to be reading this article.

The assertThrows() method is a lot like assertEquals() except that it tests to make sure a particular type of exception gets thrown during code execution.

The test passes if that exception is thrown. Otherwise, it fails.

Let's see it in action.

In Action

Here's some code that tests the method you saw above.

public void testCreateEmailCodeWithException() {
    Registrant registrant = UserHarness.getValidRegistrant();
    Mockito.when(totpUtil.getTOTPCode()).thenThrow(new RuntimeException("Problem getting code!"));
    Assertions.assertThrows(EmailCodeCreateFailedException.class, () -> registrantService.createEmailCode(registrant));

It's a not so unusual unit test called testCreateEmailCodeWithException().

First, the code instantiates a Registrant object with the assistance of a test harness. You don't need to worry about the details of that.

Then, the method employs Mockito.when() to force the application to throw a RuntimeException when the getTOTPCode() method is invoked on the totpUtil object.

Well if you go back to the first code block you'll see that any exception should cause the method to throw EmailCodeCreateFailedException. So that's what should happen in this case.

That brings us to the assertThrows() method in the last line. The first parameter in assertThrows() is the type of exception that should get thrown. In this case, it's EmailCodeCreateFailedException.class.

But what the heck is going on in that second parameter? 

That second parameter is an Executable. It's a neat way to represent a method or constructor. Here it's representing a method.

As you can see from the snippet above, it's representing exactly the method that needs to be tested: createEmailCode().

Now run that JUnit test and it will make sure that the method throws the correct type of exception when an exception is thrown during execution.

In fact, I've already run that test and it passes.

Wrapping It Up

Now you know how to use assertThrows() to test exception conditions.

Why not take some time right now to crank out a test case that checks for a specific exception under a defined set of circumstances?

Then, once you get the hang of it, write a few more test cases.

Have fun!

Photo by Juan N. Gomez from Pexels