Skip to content

Upgrading to JUnit 6.0

Marc Philipp edited this page Aug 20, 2025 · 1 revision

This page provides guidance on upgrading from JUnit 5.x.y to 6.0.0

This is currently a work in progress.

Overview

Migrating from JUnit 5.x.y to 6.0.0 should be much easier than migrating from 4.x to 5.x. Only APIs that have been deprecated for more than X have been deleted. All other APIs continue to be supported, making version 6.0.0 a drop-in replacement in most cases.

New Baselines

JUnit 6.0.0 increases the following baselines:

  • Java 17 (was 8)
  • Kotlin 2.2 (was 1.6)

Therefore, if your project uses earlier versions of Java and/or Kotlin, you should first switch to Java 17 or later and/or Kotlin 2.2 or later.

New Versioning Scheme

To simplify dependency management, all modules of JUnit Platform, Jupiter, and Vintage now use the same version number: 6.0.0. See the User Guide for a list of all artifacts.

Removed Modules

  • junit-platform-jfr (now included in junit-platform-launcher, see User Guide)
  • junit-platform-runner (without replacement)
  • junit-platform-suite-commons (now integrated into junit-platform-suite)

Removed APIs

Please refer to the release notes for a list of all removed APIs.

Null Safety

Starting with version 6.0.0, JUnit has adopted JSpecify. Its annotations are used to mark which of the types used in the API are nullable. JSpecify is supported in IDEs such as IntelliJ IDEA so you may notice new warnings when programming against JUnit's APIs. To check nullability during your build, we recommend using Error Prone and NullAway.

Deprecated APIs

JUnit Jupiter

Due to the adoption of JSpecify, the ExtensionContext.Store API was revised. Jupiter extension implementations should be changed to call the new computeIfAbsent family of methods rather than the now deprecated getOrComputeIfAbsent ones.

5.x.y
store.getOrComputeIfAbsent(MyType.class);                             // <1> returns MyType
store.getOrComputeIfAbsent("key", key -> new MyType());               // <2> returns @Nullable Object
store.getOrComputeIfAbsent("key", key -> new MyType(), MyType.class); // <3> returns @Nullable MyType
6.0.0
store.computeIfAbsent(MyType.class);                                  // <1> returns MyType
store.computeIfAbsent("key", key -> new MyType());                    // <2> returns Object
store.computeIfAbsent("key", key -> new MyType(), MyType.class);      // <3> returns MyType

JUnit Platform

In order to support cancellation of a running test execution, the existing execute methods of the Launcher API have been deprecated in favor of the new execute(LauncherExecutionRequest) method. Please refer to the User Guide for additional examples.

Launcher.execute(TestPlan, TestExecutionListener...)

5.x.y
launcher.execute(testPlan, testExecutionListener1, ..., testExecutionListenerN);
6.0.0
launcher.execute(LauncherExecutionRequestBuilder.request(testPlan)
    .listeners(testExecutionListener1, ..., testExecutionListenerN)
    .build());

Launcher.execute(LauncherDiscoveryRequest, TestExecutionListener...)

5.x.y
LauncherDiscoveryRequest discoveryRequest = LauncherDiscoveryRequestBuilder.request()
    .selectors(...)
    .filters(...)
    .build();
launcher.execute(discoveryRequest, testExecutionListener1, ..., testExecutionListenerN);
6.0.0
LauncherDiscoveryRequest discoveryRequest = LauncherDiscoveryRequestBuilder.request()
    .selectors(...)
    .filters(...)
    .build();
LauncherExecutionRequest executionRequest = LauncherExecutionRequestBuilder.request(discoveryRequest)
    .listeners(testExecutionListener1, ..., testExecutionListenerN)
    .build()
launcher.execute(executionRequest);

or

LauncherExecutionRequest executionRequest = LauncherDiscoveryRequestBuilder.request()
    .selectors(...)
    .filters(...)
    .forExecution()
    .listeners(testExecutionListener1, ..., testExecutionListenerN)
    .build();
launcher.execute(executionRequest);
Clone this wiki locally