JUnit Exception Testing

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 the testDivide method as a test method.
  • assertThrows(ArithmeticException.class, () -> { calculator.divide(10, 0); }): This line checks if the divide method throws an ArithmeticException 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 the testConvertToInt method as a test method.
  • assertThrows(NumberFormatException.class, () -> { stringUtils.convertToInt("invalid"); }): This line checks if the convertToInt method throws a NumberFormatException 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 the testSetAge method as a test method.
  • assertThrows(InvalidAgeException.class, () -> { person.setAge(-1); }): This line checks if the setAge method throws an InvalidAgeException 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.

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top