How do I understand the basic structure of a JUnit test class?

A basic JUnit test class is just a Java class that contains one or more test methods. Each test method checks whether a small piece of code behaves the way you expect.

Here is a simple JUnit 5 example:

import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.*;

class CalculatorTest {

    @Test
    void shouldAddTwoNumbers() {
        int result = 2 + 3;

        assertEquals(5, result);
    }
}

1. The Test Class

class CalculatorTest {
    // test methods go here
}

A JUnit test class is usually named after the class being tested, followed by Test.

For example:

Class Being Tested Test Class
Calculator CalculatorTest
UserService UserServiceTest
OrderRepository OrderRepositoryTest

The test class does not need a main() method. JUnit runs the tests for you.

2. The @Test Annotation

@Test
void shouldAddTwoNumbers() {
    // test code
}

The @Test annotation tells JUnit:

This method is a test method. Run it as part of the test suite.

In JUnit 5, the annotation comes from:

import org.junit.jupiter.api.Test;

3. The Test Method

A test method usually:

  1. Creates some input or test data.
  2. Runs the code being tested.
  3. Checks the result.

Example:

@Test
void shouldAddTwoNumbers() {
    int result = 2 + 3;

    assertEquals(5, result);
}

The method name should describe the expected behavior. Common naming styles include:

void shouldAddTwoNumbers()
void returnsTrueWhenPasswordIsValid()
void throwsExceptionWhenEmailIsMissing()

4. Assertions

Assertions are checks that decide whether the test passes or fails.

Common JUnit 5 assertions include:

assertEquals(expected, actual);
assertTrue(condition);
assertFalse(condition);
assertNotNull(value);
assertNull(value);
assertThrows(Exception.class, () -> {
    // code expected to throw exception
});

Example:

@Test
void shouldCheckUserName() {
    String name = "Alice";

    assertNotNull(name);
    assertEquals("Alice", name);
    assertTrue(name.startsWith("A"));
}

If all assertions pass, the test passes. If any assertion fails, the test fails.

Assertions are usually imported like this:

import static org.junit.jupiter.api.Assertions.*;

5. Basic Arrange-Act-Assert Pattern

Many test methods follow this structure:

@Test
void shouldCalculateTotalPrice() {
    // Arrange
    int price = 100;
    int quantity = 3;

    // Act
    int total = price * quantity;

    // Assert
    assertEquals(300, total);
}

Arrange

Prepare the data or objects needed for the test.

int price = 100;
int quantity = 3;

Act

Run the code you want to test.

int total = price * quantity;

Assert

Check that the result is correct.

assertEquals(300, total);

6. A Complete Basic JUnit 5 Test Class

import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.*;

class StringUtilsTest {

    @Test
    void shouldConvertTextToUpperCase() {
        // Arrange
        String text = "hello";

        // Act
        String result = text.toUpperCase();

        // Assert
        assertEquals("HELLO", result);
    }

    @Test
    void shouldCheckIfTextContainsWord() {
        // Arrange
        String text = "Learning JUnit is useful";

        // Act
        boolean containsJUnit = text.contains("JUnit");

        // Assert
        assertTrue(containsJUnit);
    }
}

7. Optional Setup Method

If several tests need the same object or data, you can use @BeforeEach.

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.*;

class CalculatorTest {

    private int baseNumber;

    @BeforeEach
    void setUp() {
        baseNumber = 10;
    }

    @Test
    void shouldAddNumber() {
        int result = baseNumber + 5;

        assertEquals(15, result);
    }

    @Test
    void shouldMultiplyNumber() {
        int result = baseNumber * 2;

        assertEquals(20, result);
    }
}

@BeforeEach runs before every test method.

8. JUnit 4 vs. JUnit 5 Structure

Older JUnit 3 or JUnit 4 tests may look different.

JUnit 5 style

import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.*;

class AppTest {

    @Test
    void shouldWork() {
        assertTrue(true);
    }
}

Older JUnit 3 style

import junit.framework.TestCase;

public class AppTest extends TestCase {

    public void testApp() {
        assertTrue(true);
    }
}

In modern Java projects, you will usually prefer JUnit 5 unless you are maintaining older code.

9. Typical Folder Location

In a Maven or Gradle Java project, test classes usually go under:

src/test/java

Application code usually goes under:

src/main/java

Example:

src
├── main
│   └── java
│       └── org.kodejava
│           └── Calculator.java
└── test
    └── java
        └── org.kodejava
            └── CalculatorTest.java

Summary

A basic JUnit test class usually has:

  1. A class name ending in Test.
  2. One or more methods annotated with @Test.
  3. Assertions such as assertEquals() or assertTrue().
  4. A clear structure: Arrange, Act, Assert.
  5. Optional setup methods such as @BeforeEach.

In short:

import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.*;

class ExampleTest {

    @Test
    void shouldDoSomething() {
        // Arrange
        String value = "JUnit";

        // Act
        boolean result = value.contains("Unit");

        // Assert
        assertTrue(result);
    }
}

Leave a Reply

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