Introduction
In this chapter, we will explore exception testing in JUnit. Exception testing is used to verify that a piece of code throws a specific exception under certain conditions. JUnit provides the assertThrows
method to facilitate this type of testing.
What is Exception Testing?
Exception testing checks whether a particular block of code throws a specific exception. This is useful for ensuring that your code handles error conditions correctly by throwing the appropriate exceptions.
Using assertThrows for Exception Testing
The assertThrows
method in JUnit is used to verify that a specific exception is thrown by a block of code. It takes three parameters:
- The expected type of the exception.
- An executable (usually a lambda expression) that should throw the exception.
- An optional message that will be shown if the test fails.
Here is the basic syntax of assertThrows
:
assertThrows(ExpectedException.class, () -> {
// Code that should throw the exception
}, "Optional failure message");
Testing Exception in a Calculator Class
Let’s use a Calculator
class that has a method for division. We will test this method to ensure it throws an ArithmeticException
when dividing by zero.
Step 1: Create the Calculator Class
public class Calculator {
public int divide(int a, int b) {
if (b == 0) {
throw new ArithmeticException("Division by zero");
}
return a / b;
}
}
Step 2: Create a Test Class
We will create a test class to test the divide
method of the Calculator
class.
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
public class CalculatorTest {
@Test
public void testDivide() {
Calculator calculator = new Calculator();
// Test for division by zero
ArithmeticException exception = assertThrows(ArithmeticException.class, () -> {
calculator.divide(10, 0);
}, "Expected ArithmeticException to be thrown");
assertEquals("Division by zero", exception.getMessage());
}
}
Explanation:
@Test
: This annotation marks thetestDivide
method as a test method.assertThrows(ArithmeticException.class, () -> { calculator.divide(10, 0); })
: This line checks if thedivide
method throws anArithmeticException
when dividing by zero.assertEquals("Division by zero", exception.getMessage())
: This assertion checks if the exception message matches the expected message.
Additional Examples
Example 1: Testing for a NumberFormatException
Let’s create a test for a method that converts a string to an integer. The method should throw a NumberFormatException
if the string is not a valid integer.
Step 1: Create the StringUtils Class
public class StringUtils {
public int convertToInt(String input) {
return Integer.parseInt(input);
}
}
Step 2: Create a Test Class
We will create a test class to test the convertToInt
method of the StringUtils
class.
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
public class StringUtilsTest {
@Test
public void testConvertToInt() {
StringUtils stringUtils = new StringUtils();
// Test for invalid integer string
NumberFormatException exception = assertThrows(NumberFormatException.class, () -> {
stringUtils.convertToInt("invalid");
}, "Expected NumberFormatException to be thrown");
assertEquals("For input string: \"invalid\"", exception.getMessage());
}
}
Explanation:
@Test
: This annotation marks thetestConvertToInt
method as a test method.assertThrows(NumberFormatException.class, () -> { stringUtils.convertToInt("invalid"); })
: This line checks if theconvertToInt
method throws aNumberFormatException
when given an invalid integer string.assertEquals("For input string: \"invalid\"", exception.getMessage())
: This assertion checks if the exception message matches the expected message.
Example 2: Testing for a Custom Exception
Let’s create a custom exception and a method that throws this exception under certain conditions.
Step 1: Create the Custom Exception
public class InvalidAgeException extends Exception {
public InvalidAgeException(String message) {
super(message);
}
}
Step 2: Create the Person Class
public class Person {
public void setAge(int age) throws InvalidAgeException {
if (age < 0) {
throw new InvalidAgeException("Age cannot be negative");
}
}
}
Step 3: Create a Test Class
We will create a test class to test the setAge
method of the Person
class.
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
public class PersonTest {
@Test
public void testSetAge() {
Person person = new Person();
// Test for invalid age
InvalidAgeException exception = assertThrows(InvalidAgeException.class, () -> {
person.setAge(-1);
}, "Expected InvalidAgeException to be thrown");
assertEquals("Age cannot be negative", exception.getMessage());
}
}
Explanation:
@Test
: This annotation marks thetestSetAge
method as a test method.assertThrows(InvalidAgeException.class, () -> { person.setAge(-1); })
: This line checks if thesetAge
method throws anInvalidAgeException
when given a negative age.assertEquals("Age cannot be negative", exception.getMessage())
: This assertion checks if the exception message matches the expected message.
Conclusion
Exception testing is an important aspect of ensuring that your code handles error conditions correctly. The assertThrows
method in JUnit makes it easy to verify that specific exceptions are thrown by your code. By mastering exception testing, you can write more robust and reliable tests for your Java applications.