JUnit 5

Language: Java

Testing

JUnit 5 was created to address limitations in JUnit 4 and provide a more flexible, extensible, and powerful testing framework. It consists of three modules: JUnit Platform, JUnit Jupiter, and JUnit Vintage, allowing developers to write modern tests and integrate with build tools and IDEs.

JUnit 5 is a modern testing framework for Java, designed to write unit and integration tests. It provides a modular architecture, rich annotations, and support for lambda expressions and assertions.

Installation

maven: Add org.junit.jupiter:junit-jupiter dependency in pom.xml
gradle: Add testImplementation 'org.junit.jupiter:junit-jupiter:5.10.0' in build.gradle

Usage

JUnit 5 allows developers to write tests using annotations such as `@Test`, `@BeforeEach`, `@AfterEach`, `@BeforeAll`, `@AfterAll`. It supports assertions, assumptions, parameterized tests, nested tests, and extensions for advanced testing scenarios.

Simple test case

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

public class CalculatorTest {
    @Test
    void additionTest() {
        assertEquals(5, 2 + 3);
    }
}

Defines a basic JUnit 5 test that checks if the addition of 2 + 3 equals 5.

Setup and teardown

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

@BeforeEach
void setup() {
    // Code executed before each test
}

@AfterEach
void teardown() {
    // Code executed after each test
}

Demonstrates methods that run before and after each test case for setup and cleanup.

Parameterized test

import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;

@ParameterizedTest
@ValueSource(ints = {1, 2, 3})
void testWithValues(int value) {
    assertTrue(value > 0);
}

Runs the same test multiple times with different input values.

Testing exceptions

@Test
void divisionByZeroTest() {
    assertThrows(ArithmeticException.class, () -> { int result = 10 / 0; });
}

Verifies that a specific exception is thrown during execution.

Nested tests

import org.junit.jupiter.api.Nested;

@Nested
class InnerTests {
    @Test
    void innerTest() {
        assertEquals(4, 2 * 2);
    }
}

Organizes tests hierarchically using nested classes for better readability.

Conditional test execution

@Test
@EnabledOnOs(OS.WINDOWS)
void runOnlyOnWindows() {
    // Test logic specific to Windows
}

Runs tests conditionally based on operating system, environment, or custom conditions.

Error Handling

Test failures: Check assertions and expected results; ensure the test logic matches the intended functionality.
NoClassDefFoundError for JUnit classes: Ensure JUnit 5 dependencies are correctly added and annotation processing is enabled if needed.

Best Practices

Write small, focused test cases for each functionality.

Use parameterized tests to avoid code duplication.

Leverage assertions to validate expected outcomes clearly.

Use `@BeforeEach` and `@AfterEach` for setup/cleanup and `@BeforeAll`/`@AfterAll` for global setup.

Integrate JUnit 5 with build tools like Maven/Gradle for automated testing pipelines.