How do I mock exceptions in JUnit tests?

In JUnit tests, you usually don’t “mock” exceptions directly. Instead, you either:

  1. Assert that real code throws an exception, or
  2. Configure a mock dependency to throw an exception.

1. Assert that code throws an exception

With JUnit 5, use assertThrows.

import org.junit.jupiter.api.Test;

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

class MyServiceTest {

    @Test
    void shouldThrowException() {
        IllegalArgumentException exception = assertThrows(
                IllegalArgumentException.class,
                () -> {
                    throw new IllegalArgumentException("Invalid input");
                }
        );

        assertEquals("Invalid input", exception.getMessage());
    }
}

assertThrows verifies that the code inside the lambda throws the expected exception type.

2. Mock a dependency to throw an exception with Mockito

If your class depends on another object, you can configure the mock to throw an exception.

import org.junit.jupiter.api.Test;
import org.mockito.Mockito;

import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.Mockito.when;

class UserServiceTest {

    @Test
    void shouldThrowWhenRepositoryFails() {
        UserRepository repository = Mockito.mock(UserRepository.class);

        when(repository.findById(1L))
                .thenThrow(new RuntimeException("Database error"));

        UserService service = new UserService(repository);

        assertThrows(
                RuntimeException.class,
                () -> service.getUser(1L)
        );
    }
}

3. Mock exceptions for void methods

For void methods, use doThrow.

import org.junit.jupiter.api.Test;
import org.mockito.Mockito;

import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.Mockito.doThrow;

class NotificationServiceTest {

    @Test
    void shouldThrowWhenEmailFails() {
        EmailClient emailClient = Mockito.mock(EmailClient.class);

        doThrow(new RuntimeException("Email failed"))
                .when(emailClient)
                .sendEmail("[email protected]");

        NotificationService service = new NotificationService(emailClient);

        assertThrows(
                RuntimeException.class,
                () -> service.notifyUser("[email protected]")
        );
    }
}

4. Check the exception message

You can capture the thrown exception and verify its message.

import org.junit.jupiter.api.Test;

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

class CalculatorTest {

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

        assertEquals("/ by zero", exception.getMessage());
    }
}

5. JUnit 4 alternative

If you are using JUnit 4, you can use the expected attribute.

import org.junit.Test;

public class CalculatorTest {

    @Test(expected = ArithmeticException.class)
    public void shouldThrowArithmeticException() {
        int result = 10 / 0;
    }
}

However, in JUnit 4, ExpectedException or AssertJ is better if you need to check the message.

import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;

public class CalculatorTest {

    @Rule
    public ExpectedException exception = ExpectedException.none();

    @Test
    public void shouldThrowWithMessage() {
        exception.expect(IllegalArgumentException.class);
        exception.expectMessage("Invalid input");

        throw new IllegalArgumentException("Invalid input");
    }
}

Quick rule of thumb

  • Use assertThrows when testing your own method throws an exception.
  • Use when(...).thenThrow(...) for mocked methods that return a value.
  • Use doThrow(...).when(...) for mocked void methods.

For modern Java projects, prefer JUnit 5 + Mockito:

assertThrows(SomeException.class, () -> service.method());

Leave a Reply

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