In JUnit tests, you usually don’t “mock” exceptions directly. Instead, you either:
- Assert that real code throws an exception, or
- 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
assertThrowswhen testing your own method throws an exception. - Use
when(...).thenThrow(...)for mocked methods that return a value. - Use
doThrow(...).when(...)for mockedvoidmethods.
For modern Java projects, prefer JUnit 5 + Mockito:
assertThrows(SomeException.class, () -> service.method());
