Updated

JUnit is a simple, open-source framework to write and run repeatable tests in Java. It’s an essential tool for any serious developer who wants to implement unit testing into their development lifecycle. Here’s how you can integrate JUnit 5 into your Maven project.

Prerequisites

Before proceeding, make sure you have:

  • Java JDK installed (Java 8 or later)
  • Apache Maven installed (3.6.0+)
  • Basic understanding of Maven project structure

Step 1: updating the pom.xml file

The first step to adding JUnit to your Maven project is to update your project’s pom.xml file. This XML file describes the software project being built, its dependencies, and the build order.

You can include JUnit in your project by adding it as a dependency. Here is how you do that:

<dependencies>
    <!-- JUnit 5 API -->
    <dependency>
        <groupId>org.junit.jupiter</groupId>
        <artifactId>junit-jupiter-api</artifactId>
        <version>5.9.3</version>
        <scope>test</scope>
    </dependency>
    <!-- JUnit 5 Engine -->
    <dependency>
        <groupId>org.junit.jupiter</groupId>
        <artifactId>junit-jupiter-engine</artifactId>
        <version>5.9.3</version>
        <scope>test</scope>
    </dependency>
</dependencies>

In the example above, I’m using JUnit version 5.9.3. You can find the latest version on Maven Central.

The <scope> tag is set to test, meaning this dependency is not required for normal use of the application, and is only available for the test compilation and execution phases.

Ensuring Maven Surefire compatibility

For Maven to properly execute JUnit 5 tests, you need the Maven Surefire plugin (version 2.22.0 or later):

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-plugin</artifactId>
            <version>3.0.0</version>
        </plugin>
    </plugins>
</build>

Step 2: writing test cases

Once the pom.xml file is updated, you can begin writing your test cases. By convention, test cases are placed in the src/test/java directory, mirroring the package structure of your main code.

Here is an example of a simple test case:

ExampleTest.java
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.DisplayName;
import static org.junit.jupiter.api.Assertions.assertEquals;

public class ExampleTest {

    @Test
    @DisplayName("Should add two numbers correctly")
    public void testAddition() {
        int a = 5;
        int b = 10;
        assertEquals(15, a + b, "5 + 10 should equal 15");
    }
}

In this test case, we’re using the @Test annotation to denote a test method and @DisplayName to provide a readable test description. The assertEquals() method checks if two values are equal, and the optional third parameter provides a failure message.

JUnit 5 common annotations

JUnit 5 provides several useful annotations for organizing tests:

import org.junit.jupiter.api.*;

public class LifecycleTest {

    @BeforeAll
    static void setupOnce() {
        // Runs once before all tests
    }

    @BeforeEach
    void setupEach() {
        // Runs before each test
    }

    @Test
    void testExample() {
        // Your test logic
    }

    @AfterEach
    void teardownEach() {
        // Runs after each test
    }

    @AfterAll
    static void teardownOnce() {
        // Runs once after all tests
    }
}

Step 3: running tests

You can run the tests using the Maven command:

mvn test

Maven will automatically discover and run any test cases in the src/test/java directory.

You should see output similar to the following if the tests pass:

-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running ExampleTest
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.028 sec

Results :
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0

[INFO] BUILD SUCCESS

The output indicates that one test was run and that there were no failures, errors, or skipped tests.

Running specific tests

You can run specific test classes or methods:

# Run a specific test class
mvn test -Dtest=ExampleTest

# Run a specific test method
mvn test -Dtest=ExampleTest#testAddition

Best practices

When integrating JUnit into your Maven projects, consider these best practices:

  • Match package structure: Keep your test packages mirrored to your source packages for easy navigation
  • Naming conventions: Name test classes with the Test suffix (e.g., CalculatorTest)
  • Descriptive test names: Use @DisplayName for human-readable test descriptions
  • Arrange-Act-Assert: Structure tests with clear setup, execution, and verification phases
  • One assertion per test: Keep tests focused on a single behavior (when practical)
  • Use parameterized tests: For testing multiple inputs, leverage @ParameterizedTest

Troubleshooting

Tests not running? Ensure you have both junit-jupiter-api and junit-jupiter-engine dependencies, and verify your Maven Surefire plugin version is 2.22.0 or later. Import errors? Run mvn clean install to refresh dependencies.

Conclusion

Integrating JUnit 5 into your Maven project is straightforward and brings significant benefits to code quality and maintainability. With proper test coverage, you can refactor with confidence, catch bugs early, and maintain a robust codebase.

Further reading

Well, now what?

You can navigate to more writings from here. Connect with me on LinkedIn for a chat.