The Named<T> interface in JUnit 5 acts as a container that pairs a payload with a custom display name. When used within a @TestFactory, it allows you to dynamically generate test cases where the display name is decoupled from the actual data object's toString() representation.
This is particularly useful when testing complex objects or domain entities where you want the test report to show a human-readable description (e.g., "Admin User with special characters") rather than a cryptic object hash or a verbose string of all fields. It provides the same naming flexibility for dynamic tests that @ParameterizedTest(name = "...") offers for parameterized tests.
Java source and doc
Definition of NamedVersion: 6.0.0 package org.junit.jupiter.api;
@API(status = STABLE, since = "5.8")
public interface Named<T extends @Nullable Object> {
static <T extends @Nullable Object> Named<T> of(String name, T payload) { 1
...
}
static <T extends @Nullable Object> Named<T> named(String name, T payload) { 2
...
}
String getName(); 3
T getPayload(); 4
}
Example
package com.logicbig.example;
import org.junit.jupiter.api.DynamicTest;
import org.junit.jupiter.api.Named;
import org.junit.jupiter.api.TestFactory;
import java.util.stream.Stream;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.DynamicTest.dynamicTest;
public class DynamicTestsNamedTest {
@TestFactory
Stream<DynamicTest> dynamicTestsWithNamed() {
return Stream.of(
Named.of("Small prime", 7),
Named.of("Large even number", 100),
Named.of("Minimum positive integer", 1)
).map(named -> dynamicTest(named.getName(), () -> {
Integer value = named.getPayload();
System.out.println("Testing value: " + value);
assertTrue(value > 0);
}));
}
}
Output$ mvn test -Dtest=DynamicTestsNamedTest [INFO] Scanning for projects... [INFO] [INFO] ----------< com.logicbig.example:junit-5-dynamic-tests-named >---------- [INFO] Building junit-5-dynamic-tests-named 1.0-SNAPSHOT [INFO] from pom.xml [INFO] --------------------------------[ jar ]--------------------------------- [INFO] [INFO] --- resources:3.3.1:resources (default-resources) @ junit-5-dynamic-tests-named --- [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-dynamic-tests\junit-5-dynamic-tests-named\src\main\resources [INFO] [INFO] --- compiler:3.13.0:compile (default-compile) @ junit-5-dynamic-tests-named --- [INFO] No sources to compile [INFO] [INFO] --- resources:3.3.1:testResources (default-testResources) @ junit-5-dynamic-tests-named --- [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-dynamic-tests\junit-5-dynamic-tests-named\src\test\resources [INFO] [INFO] --- compiler:3.13.0:testCompile (default-testCompile) @ junit-5-dynamic-tests-named --- [INFO] Recompiling the module because of changed source code. [WARNING] File encoding has not been set, using platform encoding windows-1252, i.e. build is platform dependent! [INFO] Compiling 1 source file with javac [debug target 17] to target\test-classes [INFO] [INFO] --- surefire:3.5.0:test (default-test) @ junit-5-dynamic-tests-named --- [INFO] Using auto detected provider org.apache.maven.surefire.junitplatform.JUnitPlatformProvider [INFO] [INFO] ------------------------------------------------------- [INFO] T E S T S [INFO] ------------------------------------------------------- Testing value: 7 Testing value: 100 Testing value: 1 [INFO] +--com.logicbig.example.DynamicTestsNamedTest - 0.118 ss [INFO] | +-- [OK] dynamicTestsWithNamed() Small prime - 0.017 ss [INFO] | +-- [OK] dynamicTestsWithNamed() Large even number - 0.001 ss [INFO] | '-- [OK] dynamicTestsWithNamed() Minimum positive integer - 0.002 ss [INFO] [INFO] Results: [INFO] [INFO] Tests run: 3, Failures: 0, Errors: 0, Skipped: 0 [INFO] [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 4.415 s [INFO] Finished at: 2025-12-28T15:16:45+08:00 [INFO] ------------------------------------------------------------------------
Output Analysis
The output above demonstrates how the Named interface allows us to assign descriptive labels to our test inputs. Even though the test logic uses the underlying integer payload, the JUnit report displays the custom strings like "Small prime" and "Large even number". This confirms that using Named.of() effectively overrides the default display naming behavior, making dynamic test results significantly easier to interpret in build logs and IDEs.
Example ProjectDependencies and Technologies Used: - junit-jupiter-engine 6.0.1 (Module "junit-jupiter-engine" of JUnit)
Version Compatibility: 5.8.0 - 6.0.1 Version compatibilities of junit-jupiter-engine with this example:
- 5.8.0
- 5.8.1
- 5.8.2
- 5.9.0
- 5.9.1
- 5.9.2
- 5.9.3
- 5.10.0
- 5.10.1
- 5.10.2
- 5.10.3
- 5.10.4
- 5.10.5
- 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.
- JDK 25
- Maven 3.9.11
|