JUnit Nested Tests

Introduction

In this chapter, we will explore JUnit nested tests. Nested tests allow you to logically group test classes within a single test class. This is useful for organizing tests that share a common context or setup, making your test suite easier to maintain and understand.

What are Nested Tests?

Nested tests are a way to structure your tests hierarchically by nesting test classes within each other. This helps in grouping related tests together and setting up shared context more effectively. JUnit 5 provides the @Nested annotation to create nested test classes.

Overview of @Nested Annotation

The @Nested annotation is used to define a nested test class. This annotation indicates that the enclosed class is a nested, non-static test class, which can contain its own lifecycle methods and test methods. Nested tests can help to:

  • Organize tests that share a common setup.
  • Group related tests logically.
  • Provide a clear structure for complex test scenarios.

Example: Creating Nested Tests

Let’s create nested tests for a simple Account class to demonstrate how nested tests can be used to organize tests.

Step 1: Create Class Under Test

Account Class

The Account class will have methods for deposit, withdrawal, and checking the balance.

public class Account {
    private double balance;

    public Account(double initialBalance) {
        if (initialBalance < 0) {
            throw new IllegalArgumentException("Initial balance cannot be negative");
        }
        this.balance = initialBalance;
    }

    public void deposit(double amount) {
        if (amount <= 0) {
            throw new IllegalArgumentException("Deposit amount must be positive");
        }
        balance += amount;
    }

    public void withdraw(double amount) {
        if (amount <= 0) {
            throw new IllegalArgumentException("Withdrawal amount must be positive");
        }
        if (amount > balance) {
            throw new IllegalArgumentException("Insufficient funds");
        }
        balance -= amount;
    }

    public double getBalance() {
        return balance;
    }
}

Step 2: Create Nested Test Class

AccountTest

The AccountTest class will contain nested test classes to group tests logically.

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;

public class AccountTest {

    private Account account;

    @Nested
    class WhenNew {

        @BeforeEach
        void setUp() {
            account = new Account(100.0);
        }

        @Test
        void initialBalanceIsSet() {
            assertEquals(100.0, account.getBalance());
        }

        @Test
        void depositIncreasesBalance() {
            account.deposit(50.0);
            assertEquals(150.0, account.getBalance());
        }

        @Test
        void withdrawalDecreasesBalance() {
            account.withdraw(50.0);
            assertEquals(50.0, account.getBalance());
        }

        @Test
        void withdrawalWithInsufficientFundsThrowsException() {
            Exception exception = assertThrows(IllegalArgumentException.class, () -> {
                account.withdraw(150.0);
            });
            assertEquals("Insufficient funds", exception.getMessage());
        }
    }

    @Nested
    class WhenOverdrawn {

        @BeforeEach
        void setUp() {
            account = new Account(50.0);
            account.withdraw(50.0);
        }

        @Test
        void balanceIsZero() {
            assertEquals(0.0, account.getBalance());
        }

        @Test
        void depositIncreasesBalance() {
            account.deposit(50.0);
            assertEquals(50.0, account.getBalance());
        }

        @Test
        void withdrawalThrowsException() {
            Exception exception = assertThrows(IllegalArgumentException.class, () -> {
                account.withdraw(10.0);
            });
            assertEquals("Insufficient funds", exception.getMessage());
        }
    }
}

Important Points

Explanation of the Nested Test Class

  • @Nested: This annotation marks the enclosed class as a nested, non-static test class.
  • @BeforeEach: This annotation marks a method to be run before each test method in the enclosing class. It is used here to set up a common Account instance for all nested tests.
  • WhenNew, WhenOverdrawn: These are nested test classes that group related tests together.

Running the Nested Tests using IntelliJ IDEA

To run the nested tests, simply run the AccountTest class as a JUnit test. This will execute all the test methods in the nested test classes.

  1. Run Nested Tests: Click the green run icon next to the AccountTest class and select Run.
  2. View Results: The results will be displayed in the Run window. A green check mark indicates that all tests passed, while a red cross indicates that some tests failed.

JUnit Nested Tests

Conclusion

JUnit nested tests are a powerful way to organize and manage your tests. By grouping related test classes within a single test class, you can run all relevant tests together and get a comprehensive view of your test results. Nested tests help you maintain a clear structure for complex test scenarios, making it easier to manage large test sets in your Java projects.

Leave a Comment

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

Scroll to Top