JUnit Jupiter API for writing tests - Core API module of JUnit 5 that provides annotations, assertions, and test lifecycle management
—
Essential testing annotations, assertions, and lifecycle management providing the foundation for all JUnit Jupiter testing scenarios. This includes test method marking, setup/teardown hooks, comprehensive assertion methods, and test organization features.
Core annotations for marking test methods and controlling test lifecycle.
/**
* Marks a method as a test method. Test methods must not be private or static and must not return a value.
*/
@Test
/**
* Executed before each test method in the current class
*/
@BeforeEach
/**
* Executed after each test method in the current class
*/
@AfterEach
/**
* Executed once before all test methods in the current class (static methods only)
*/
@BeforeAll
/**
* Executed once after all test methods in the current class (static methods only)
*/
@AfterAllUsage Examples:
import org.junit.jupiter.api.*;
class UserServiceTest {
private UserService userService;
private static DatabaseConnection connection;
@BeforeAll
static void initDatabase() {
connection = DatabaseConnection.create();
}
@BeforeEach
void setUp() {
userService = new UserService(connection);
}
@Test
void shouldCreateUser() {
User user = userService.createUser("john", "john@example.com");
assertNotNull(user);
assertEquals("john", user.getName());
}
@AfterEach
void tearDown() {
userService.cleanup();
}
@AfterAll
static void closeDatabase() {
connection.close();
}
}Annotations for organizing, describing, and controlling test execution.
/**
* Provides a custom display name for the test class or test method
* @param value Custom display name
*/
@DisplayName(String value)
/**
* Disables a test class or test method
* @param value Optional reason for disabling
*/
@Disabled(String value)
/**
* Tags a test class or test method for filtering during test execution
* @param value Tag name
*/
@Tag(String value)
/**
* Container for multiple @Tag annotations
*/
@Tags({@Tag("integration"), @Tag("slow")})
/**
* Marks a test class as a nested test class
*/
@NestedUsage Examples:
@DisplayName("User Account Management")
class UserAccountTest {
@Test
@DisplayName("Creating user with valid email should succeed")
@Tag("unit")
void validEmailCreation() {
// test implementation
}
@Test
@Disabled("Feature not implemented yet")
void premiumFeatureTest() {
// test implementation
}
@Nested
@DisplayName("Password Management")
class PasswordTests {
@Test
@Tags({@Tag("security"), @Tag("integration")})
void shouldEncryptPassword() {
// nested test implementation
}
}
}Comprehensive static assertion methods in the Assertions class for validating test conditions.
import java.util.function.Supplier;
/**
* Boolean assertions
*/
static void assertTrue(boolean condition);
static void assertTrue(boolean condition, String message);
static void assertTrue(boolean condition, Supplier<String> messageSupplier);
static void assertFalse(boolean condition);
static void assertFalse(boolean condition, String message);
static void assertFalse(boolean condition, Supplier<String> messageSupplier);
/**
* Equality assertions
*/
static void assertEquals(Object expected, Object actual);
static void assertEquals(Object expected, Object actual, String message);
static void assertEquals(Object expected, Object actual, Supplier<String> messageSupplier);
static void assertNotEquals(Object unexpected, Object actual);
static void assertNotEquals(Object unexpected, Object actual, String message);
/**
* Null checks
*/
static void assertNull(Object actual);
static void assertNull(Object actual, String message);
static void assertNotNull(Object actual);
static void assertNotNull(Object actual, String message);
/**
* Reference equality
*/
static void assertSame(Object expected, Object actual);
static void assertSame(Object expected, Object actual, String message);
static void assertNotSame(Object unexpected, Object actual);
static void assertNotSame(Object unexpected, Object actual, String message);Usage Examples:
import static org.junit.jupiter.api.Assertions.*;
@Test
void testUserCreation() {
// Boolean assertions
assertTrue(user.isActive(), "User should be active by default");
assertFalse(user.isDeleted());
// Equality assertions
assertEquals("john", user.getName());
assertEquals(25, user.getAge(), "Age should match");
assertNotEquals("admin", user.getRole());
// Null checks
assertNotNull(user.getId(), "User ID should not be null");
assertNotNull(user.getCreatedAt());
// Reference equality
User sameUser = userRepository.findById(user.getId());
assertEquals(user, sameUser); // value equality
assertNotSame(user, sameUser); // different object references
}Assertions for testing expected exceptions and error conditions.
import java.util.function.Supplier;
import org.junit.jupiter.api.function.Executable;
import org.junit.jupiter.api.function.ThrowingSupplier;
/**
* Assert that execution throws an exception of specified type
*/
static <T extends Throwable> T assertThrows(Class<T> expectedType, Executable executable);
static <T extends Throwable> T assertThrows(Class<T> expectedType, Executable executable, String message);
static <T extends Throwable> T assertThrows(Class<T> expectedType, Executable executable, Supplier<String> messageSupplier);
/**
* Assert that execution does not throw any exception
*/
static void assertDoesNotThrow(Executable executable);
static void assertDoesNotThrow(Executable executable, String message);
static <T> T assertDoesNotThrow(ThrowingSupplier<T> supplier);
static <T> T assertDoesNotThrow(ThrowingSupplier<T> supplier, String message);Usage Examples:
@Test
void testExceptionHandling() {
UserService userService = new UserService();
// Test expected exception
IllegalArgumentException exception = assertThrows(
IllegalArgumentException.class,
() -> userService.createUser(null, "email@example.com"),
"Creating user with null name should throw IllegalArgumentException"
);
assertEquals("Name cannot be null", exception.getMessage());
// Test no exception thrown
assertDoesNotThrow(() -> userService.createUser("john", "john@example.com"));
// Test no exception with return value
User user = assertDoesNotThrow(() -> userService.findById(123L));
assertNotNull(user);
}Assertions for testing execution time constraints.
import java.time.Duration;
import org.junit.jupiter.api.function.Executable;
import org.junit.jupiter.api.function.ThrowingSupplier;
/**
* Assert that execution completes before the given timeout
*/
static void assertTimeout(Duration timeout, Executable executable);
static void assertTimeout(Duration timeout, Executable executable, String message);
static <T> T assertTimeout(Duration timeout, ThrowingSupplier<T> supplier);
static <T> T assertTimeout(Duration timeout, ThrowingSupplier<T> supplier, String message);
/**
* Assert that execution completes before timeout, preemptively aborting if it exceeds
*/
static void assertTimeoutPreemptively(Duration timeout, Executable executable);
static void assertTimeoutPreemptively(Duration timeout, Executable executable, String message);
static <T> T assertTimeoutPreemptively(Duration timeout, ThrowingSupplier<T> supplier);Usage Examples:
import java.time.Duration;
@Test
void testPerformance() {
// Test completes within timeout (waits for completion)
assertTimeout(Duration.ofSeconds(2), () -> {
userService.processLargeDataSet();
}, "Data processing should complete within 2 seconds");
// Test completes within timeout, preemptively abort if exceeded
String result = assertTimeoutPreemptively(Duration.ofMillis(500), () -> {
return fastComputationService.calculate();
});
assertNotNull(result);
}Assertions for validating multiple conditions together.
import java.util.Collection;
import java.util.stream.Stream;
import org.junit.jupiter.api.function.Executable;
/**
* Group multiple assertions together - all are executed even if some fail
*/
static void assertAll(Executable... executables);
static void assertAll(String heading, Executable... executables);
static void assertAll(Collection<Executable> executables);
static void assertAll(String heading, Collection<Executable> executables);
static void assertAll(Stream<Executable> executables);
static void assertAll(String heading, Stream<Executable> executables);Usage Examples:
@Test
void testUserProperties() {
User user = userService.createUser("john", "john@example.com", 25);
// Group related assertions
assertAll("User properties",
() -> assertEquals("john", user.getName()),
() -> assertEquals("john@example.com", user.getEmail()),
() -> assertEquals(25, user.getAge()),
() -> assertTrue(user.isActive()),
() -> assertNotNull(user.getId())
);
// All assertions execute even if some fail
assertAll("Validation checks",
() -> assertTrue(user.getName().length() > 0),
() -> assertEquals("gmail.com", user.getEmail().split("@")[1]), // might fail
() -> assertTrue(user.getAge() >= 18) // still executes
);
}Specialized assertions for collections, arrays, and iterables.
/**
* Array equality assertions
*/
static void assertArrayEquals(Object[] expected, Object[] actual);
static void assertArrayEquals(Object[] expected, Object[] actual, String message);
static void assertArrayEquals(boolean[] expected, boolean[] actual);
static void assertArrayEquals(byte[] expected, byte[] actual);
static void assertArrayEquals(char[] expected, char[] actual);
static void assertArrayEquals(double[] expected, double[] actual, double delta);
static void assertArrayEquals(float[] expected, float[] actual, float delta);
static void assertArrayEquals(int[] expected, int[] actual);
static void assertArrayEquals(long[] expected, long[] actual);
static void assertArrayEquals(short[] expected, short[] actual);
/**
* Iterable equality assertions
*/
static void assertIterableEquals(Iterable<?> expected, Iterable<?> actual);
static void assertIterableEquals(Iterable<?> expected, Iterable<?> actual, String message);
/**
* Line-by-line string comparison
*/
static void assertLinesMatch(java.util.List<String> expectedLines, java.util.List<String> actualLines);
static void assertLinesMatch(java.util.List<String> expectedLines, java.util.List<String> actualLines, String message);
static void assertLinesMatch(java.util.stream.Stream<String> expectedLines, java.util.stream.Stream<String> actualLines);Usage Examples:
@Test
void testCollections() {
int[] expectedScores = {95, 87, 92, 88};
int[] actualScores = calculateScores();
assertArrayEquals(expectedScores, actualScores, "Scores should match expected values");
List<String> expectedNames = Arrays.asList("Alice", "Bob", "Charlie");
List<String> actualNames = userService.getUserNames();
assertIterableEquals(expectedNames, actualNames);
List<String> expectedOutput = Arrays.asList(
"Processing started",
">> \\d+ records processed", // regex pattern
"Processing completed"
);
List<String> actualOutput = captureConsoleOutput();
assertLinesMatch(expectedOutput, actualOutput);
}Assertions for testing object types and instance relationships.
/**
* Assert that an object is an instance of the expected type
*/
static <T> T assertInstanceOf(Class<T> expectedType, Object actualValue);
static <T> T assertInstanceOf(Class<T> expectedType, Object actualValue, String message);
static <T> T assertInstanceOf(Class<T> expectedType, Object actualValue, Supplier<String> messageSupplier);Usage Examples:
@Test
void testInstanceTypes() {
Object result = serviceFactory.createService("user");
// Assert type and get typed reference
UserService userService = assertInstanceOf(UserService.class, result,
"Factory should create UserService instance");
// Now can safely use typed methods
assertEquals("UserService", userService.getServiceName());
}Conditional test execution based on runtime conditions using the Assumptions class.
import java.util.function.BooleanSupplier;
import java.util.function.Supplier;
import org.junit.jupiter.api.function.Executable;
/**
* Validate assumption and abort test if false
*/
static void assumeTrue(boolean assumption);
static void assumeTrue(boolean assumption, String message);
static void assumeTrue(boolean assumption, Supplier<String> messageSupplier);
static void assumeTrue(BooleanSupplier assumptionSupplier);
static void assumeTrue(BooleanSupplier assumptionSupplier, String message);
static void assumeFalse(boolean assumption);
static void assumeFalse(boolean assumption, String message);
static void assumeFalse(BooleanSupplier assumptionSupplier);
/**
* Execute executable only if assumption is true
*/
static void assumingThat(boolean assumption, Executable executable);
static void assumingThat(BooleanSupplier assumptionSupplier, Executable executable);
/**
* Explicitly abort test execution - generic return type allows use in expressions
*/
static <V> V abort();
static <V> V abort(String message);
static <V> V abort(Supplier<String> messageSupplier);Usage Examples:
import static org.junit.jupiter.api.Assumptions.*;
@Test
void testDatabaseFeature() {
// Assume database is available, abort test if not
assumeTrue(isDatabaseAvailable(), "Database must be available for this test");
// Test will only run if assumption passes
User user = userRepository.save(new User("test"));
assertNotNull(user.getId());
}
@Test
void testOptionalFeature() {
// Execute part of test only if condition met
assumingThat(isFeatureEnabled("premium"), () -> {
PremiumService service = new PremiumService();
assertTrue(service.isPremiumFeatureAvailable());
});
// This part always executes
BasicService basicService = new BasicService();
assertTrue(basicService.isBasicFeatureAvailable());
}import java.lang.reflect.Method;
import java.util.Optional;
import java.util.Set;
import java.util.Map;
/**
* Provides information about the current test
*/
interface TestInfo {
String getDisplayName();
Set<String> getTags();
Optional<Class<?>> getTestClass();
Optional<Method> getTestMethod();
}
/**
* Publishes entries (key-value pairs) for the current test
*/
interface TestReporter {
void publishEntry(Map<String, String> map);
void publishEntry(String key, String value);
}
/**
* Information about the current repetition of a repeated test
*/
interface RepetitionInfo {
int getCurrentRepetition();
int getTotalRepetitions();
}/**
* Configuration for test instance lifecycle
*/
@TestInstance(TestInstance.Lifecycle value)
enum TestInstance.Lifecycle {
/**
* New test instance created for each test method (default)
*/
PER_METHOD,
/**
* Same test instance used for all test methods in a class
*/
PER_CLASS
}/**
* Configure the order in which test methods are executed
*/
@TestMethodOrder(Class<? extends MethodOrderer> value)
/**
* Specify execution order for a test method
*/
@Order(int value)
/**
* Strategy interface for ordering test methods
*/
interface MethodOrderer {
void orderMethods(Context context);
// Built-in implementations
class DisplayName implements MethodOrderer { }
class MethodName implements MethodOrderer { }
class OrderAnnotation implements MethodOrderer { }
class Random implements MethodOrderer { }
}/**
* Repeats a test a specified number of times
*/
@RepeatedTest(
int value,
String name = "",
FailureThreshold failureThreshold = @FailureThreshold
)
/**
* Controls when repeated test execution should stop on failures
*/
@FailureThreshold(int value)/**
* A test case generated at runtime
*/
class DynamicTest implements DynamicNode {
static DynamicTest dynamicTest(String displayName, Executable executable);
static DynamicTest dynamicTest(String displayName, java.net.URI testSourceUri, Executable executable);
static java.util.stream.Stream<DynamicTest> stream(java.util.Iterator<String> inputGenerator,
java.util.function.Function<String, String> displayNameGenerator,
ThrowingConsumer<String> testExecutor);
}
/**
* A container for dynamic tests
*/
class DynamicContainer implements DynamicNode {
static DynamicContainer dynamicContainer(String displayName, Iterable<? extends DynamicNode> dynamicNodes);
static DynamicContainer dynamicContainer(String displayName, java.net.URI testSourceUri, Iterable<? extends DynamicNode> dynamicNodes);
static DynamicContainer dynamicContainer(String displayName, java.util.stream.Stream<? extends DynamicNode> dynamicNodes);
}
/**
* Factory method for generating dynamic tests at runtime
*/
@TestFactoryContainer interfaces for associating names with payloads and executables for dynamic test generation.
import org.junit.jupiter.api.Named;
import org.junit.jupiter.api.NamedExecutable;
import org.junit.jupiter.api.function.Executable;
/**
* Container that associates a name with a given payload
* @param <T> the type of the payload
*/
interface Named<T> {
/**
* Factory method for creating an instance of Named based on a name and a payload
* @param name the name associated with the payload; never null or blank
* @param payload the object that serves as the payload; may be null
* @param <T> the type of the payload
* @return an instance of Named; never null
*/
static <T> Named<T> of(String name, T payload);
/**
* Factory method for creating an instance of Named (alias for of method)
* @param name the name associated with the payload; never null or blank
* @param payload the object that serves as the payload; may be null
* @param <T> the type of the payload
* @return an instance of Named; never null
*/
static <T> Named<T> named(String name, T payload);
/**
* Get the name of the payload
* @return the name of the payload; never null or blank
*/
String getName();
/**
* Get the payload
* @return the payload; may be null depending on the use case
*/
T getPayload();
}
/**
* Joins Executable and Named in a single functional interface
*/
@FunctionalInterface
interface NamedExecutable extends Named<Executable>, Executable {
@Override
default String getName() {
return toString();
}
@Override
default Executable getPayload() {
return this;
}
}Complete method signatures for all DynamicTest streaming methods with Named interfaces.
import java.net.URI;
import java.util.Iterator;
import java.util.function.Function;
import java.util.stream.Stream;
import org.junit.jupiter.api.function.Executable;
import org.junit.jupiter.api.function.ThrowingConsumer;
import org.junit.jupiter.api.Named;
class DynamicTest implements DynamicNode {
// Basic factory methods
static DynamicTest dynamicTest(String displayName, Executable executable);
static DynamicTest dynamicTest(String displayName, URI testSourceUri, Executable executable);
// Stream with input generator and display name generator
static <T> Stream<DynamicTest> stream(Iterator<T> inputGenerator,
Function<? super T, String> displayNameGenerator,
ThrowingConsumer<? super T> testExecutor);
static <T> Stream<DynamicTest> stream(Stream<T> inputStream,
Function<? super T, String> displayNameGenerator,
ThrowingConsumer<? super T> testExecutor);
// Stream with Named input values
static <T> Stream<DynamicTest> stream(Iterator<? extends Named<T>> inputGenerator,
ThrowingConsumer<? super T> testExecutor);
static <T> Stream<DynamicTest> stream(Stream<? extends Named<T>> inputStream,
ThrowingConsumer<? super T> testExecutor);
// Stream with NamedExecutable (experimental)
static <T extends Named<E>, E extends Executable> Stream<DynamicTest> stream(
Iterator<? extends T> iterator);
static <T extends Named<E>, E extends Executable> Stream<DynamicTest> stream(
Stream<? extends T> inputStream);
}Install with Tessl CLI
npx tessl i tessl/maven-org-junit-jupiter--junit-jupiter-api