How do I test exceptions with assertThrows()?

Testing Exceptions with assertThrows() in JUnit 5

Use assertThrows() when you expect a piece of code to throw a specific exception.

Basic Syntax

ExceptionType exception = assertThrows(
        ExceptionType.class,
        () -> {
            // code that should throw the exception
        }
);

For JUnit 5, import it like this:

import org.junit.jupiter.api.Test;

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

Simple Example

import org.junit.jupiter.api.Test;

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

class DivisionTest {

    @Test
    void divideByZeroThrowsArithmeticException() {
        assertThrows(ArithmeticException.class, () -> {
            int result = 10 / 0;
        });
    }
}

If 10 / 0 throws an ArithmeticException, the test passes.

If no exception is thrown, or a different exception is thrown, the test fails.


Checking the Exception Message

assertThrows() returns the thrown exception, so you can inspect it.

import org.junit.jupiter.api.Test;

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

class UserServiceTest {

    @Test
    void rejectsInvalidUserId() {
        IllegalArgumentException exception = assertThrows(
                IllegalArgumentException.class,
                () -> validateUserId(-1)
        );

        assertEquals("User ID must be positive", exception.getMessage());
    }

    private void validateUserId(int userId) {
        if (userId <= 0) {
            throw new IllegalArgumentException("User ID must be positive");
        }
    }
}

Testing a Method That Throws an Exception

Suppose you have this method:

public int divide(int a, int b) {
    if (b == 0) {
        throw new IllegalArgumentException("Divider cannot be zero");
    }

    return a / b;
}

You can test it like this:

import org.junit.jupiter.api.Test;

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

class CalculatorTest {

    private final Calculator calculator = new Calculator();

    @Test
    void divideThrowsExceptionWhenDividerIsZero() {
        IllegalArgumentException exception = assertThrows(
                IllegalArgumentException.class,
                () -> calculator.divide(10, 0)
        );

        assertEquals("Divider cannot be zero", exception.getMessage());
    }
}

Short Form

If you only care that the exception is thrown, you do not need to store it:

@Test
void invalidInputThrowsException() {
    assertThrows(
            IllegalArgumentException.class,
            () -> someMethod("invalid")
    );
}

Important Notes

  • The code that should throw the exception goes inside the lambda: () -> ...
  • The expected exception type goes first: IllegalArgumentException.class
  • The test passes only if that exception type, or a subclass of it, is thrown.
  • If you want an exact exception type match, use assertThrowsExactly().

Example:

@Test
void throwsExactlyIllegalArgumentException() {
    assertThrowsExactly(
            IllegalArgumentException.class,
            () -> someMethod("invalid")
    );
}

You would need this import:

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

Common Mistake

Do not call the method before assertThrows():

// Wrong
someMethod("invalid");
assertThrows(IllegalArgumentException.class, () -> {});

Instead, call the method inside the lambda:

// Correct
assertThrows(
        IllegalArgumentException.class,
        () -> someMethod("invalid")
);

Summary

Use assertThrows() like this:

@Test
void methodThrowsExpectedException() {
    Exception exception = assertThrows(
            Exception.class,
            () -> methodThatShouldThrow()
    );

    assertEquals("Expected message", exception.getMessage());
}

It verifies that the code throws the expected exception and optionally lets you check details such as the exception message.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.