Close

JUnit 5 - @BeforeSuite and @AfterSuite Usage

[Last Updated: Dec 22, 2025]

JUnit provides @BeforeSuite and @AfterSuite annotations to support initialization and cleanup logic that must run exactly once for an entire test suite. Unlike @BeforeAll and @AfterAll, these callbacks operate at the JUnit Platform suite level and are executed outside individual test classes.

When to use suite-level callbacks

Suite-level callbacks are useful when tests depend on shared infrastructure such as external services, databases, or global configuration that should be initialized once before any test runs and cleaned up only after all tests have completed.

Suite definition and lifecycle hooks

The suite class acts as the orchestration entry point. It selects test classes and hosts the @BeforeSuite and @AfterSuite methods.

Definition of BeforeSuite

Version: 6.0.0
 package org.junit.platform.suite.api;
 @Target(ElementType.METHOD)
 @Retention(RetentionPolicy.RUNTIME)
 @Documented
 @API(status = MAINTAINED, since = "1.13.3")
 public @interface BeforeSuite {
 }

Definition of AfterSuite

Version: 6.0.0
 package org.junit.platform.suite.api;
 @Target(ElementType.METHOD)
 @Retention(RetentionPolicy.RUNTIME)
 @Documented
 @API(status = MAINTAINED, since = "1.13.3")
 public @interface AfterSuite {
 }

Example

Shared Database class

package com.logicbig.example;

import java.util.HashMap;
import java.util.Map;

public class DbService {

    private static final DbService INSTANCE = new DbService();
    private Map<String, String> data;

    private DbService() {
    }

    public static DbService getInstance() {
        return INSTANCE;
    }

    public void connect(){
        //just initializing a map for demo
        data = new HashMap<>();
        data.put("itemCount", "1000");
    }

    public String getData(String name){
        if(data==null){
            throw new RuntimeException("data not initialized");
        }
        return data.get(name);
    }

    public void disconnect(){
        data = null;
    }
}

Test class

package com.logicbig.example;

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

public class SimpleServiceTest {

    @Test
    void serviceWorks() {
        System.out.println("Test executed");
        assertEquals("1000", DbService.getInstance()
                                      .getData("itemCount"));
    }
}

Suite Class

package com.logicbig.example;

import org.junit.platform.suite.api.AfterSuite;
import org.junit.platform.suite.api.BeforeSuite;
import org.junit.platform.suite.api.SelectClasses;
import org.junit.platform.suite.api.Suite;

@Suite
@SelectClasses(SimpleServiceTest.class)
public class BeforeAfterSuiteExampleSuite {

    @BeforeSuite
    static void beforeSuite() {
        System.out.println("Suite setup");
        DbService.getInstance().connect();
    }

    @AfterSuite
    static void afterSuite() {
        System.out.println("Suite cleanup");
          DbService.getInstance().disconnect();
    }
}

Output

$ mvn test -Dtest=BeforeAfterSuiteExampleSuite
[INFO] Scanning for projects...
[INFO]
[INFO] -------< com.logicbig.example:junit-5-before-after-suite-usage >--------
[INFO] Building junit-5-before-after-suite-usage 1.0-SNAPSHOT
[INFO] from pom.xml
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- resources:3.3.1:resources (default-resources) @ junit-5-before-after-suite-usage ---
[WARNING] Using platform encoding (Cp1252 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] skip non existing resourceDirectory D:\example-projects\junit-5\junit-5-suite-engine\junit-5-before-after-suite-usage\src\main\resources
[INFO]
[INFO] --- compiler:3.11.0:compile (default-compile) @ junit-5-before-after-suite-usage ---
[INFO] No sources to compile
[INFO]
[INFO] --- resources:3.3.1:testResources (default-testResources) @ junit-5-before-after-suite-usage ---
[WARNING] Using platform encoding (Cp1252 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] skip non existing resourceDirectory D:\example-projects\junit-5\junit-5-suite-engine\junit-5-before-after-suite-usage\src\test\resources
[INFO]
[INFO] --- compiler:3.11.0:testCompile (default-testCompile) @ junit-5-before-after-suite-usage ---
[INFO] Nothing to compile - all classes are up to date
[INFO]
[INFO] --- surefire:3.5.0:test (default-test) @ junit-5-before-after-suite-usage ---
[INFO] Using auto detected provider org.apache.maven.surefire.junitplatform.JUnitPlatformProvider
[INFO]
[INFO] -------------------------------------------------------
[INFO] T E S T S
[INFO] -------------------------------------------------------
Suite setup
Test executed
[INFO] +--BeforeAfterSuiteExampleSuite SimpleServiceTest - 0.055 ss
[INFO] | '-- [OK] serviceWorks - 0.041 ss
Suite cleanup
[INFO]
[INFO] Results:
[INFO]
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 3.494 s
[INFO] Finished at: 2025-12-22T00:10:32+08:00
[INFO] ------------------------------------------------------------------------

The output of this example is expected because the suite engine guarantees that @BeforeSuite executes once before any selected test classes are run, and @AfterSuite executes once after all tests have completed. The appearance of the setup message before the test output, followed by the teardown message at the very end, confirms that the lifecycle hooks are bound to the suite execution rather than individual test classes.

Example Project

Dependencies and Technologies Used:

  • junit-jupiter-engine 6.0.1 (Module "junit-jupiter-engine" of JUnit)
     Version Compatibility: 5.11.0 - 6.0.1Version List
    ×

    Version compatibilities of junit-jupiter-engine with this example:

    • 5.11.0
    • 5.11.1
    • 5.11.2
    • 5.11.3
    • 5.11.4
    • 5.12.0
    • 5.12.1
    • 5.12.2
    • 5.13.0
    • 5.13.1
    • 5.13.2
    • 5.13.3
    • 5.13.4
    • 5.14.0
    • 5.14.1
    • 6.0.0
    • 6.0.1

    Versions in green have been tested.

  • junit-platform-suite-engine 6.0.1 (Module "junit-platform-suite-engine" of JUnit)
  • JDK 25
  • Maven 3.9.11

JUnit 5 - @BeforeSuite and @AfterSuite Usage Select All Download
  • junit-5-before-after-suite-usage
    • src
      • test
        • java
          • com
            • logicbig
              • example
                • BeforeAfterSuiteExampleSuite.java

    See Also