CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-org-junit-jupiter--junit-jupiter-params

JUnit Jupiter extension for parameterized tests

Pending
Overview
Eval results
Files

enum-method-sources.mddocs/

Enum and Method Sources

Advanced argument providers for enum constants, method-generated arguments, and field-based data sources.

Capabilities

@EnumSource Annotation

Provides enum constants as test arguments with flexible selection modes and filtering options.

/**
 * Provides enum constants as arguments to parameterized tests
 */
@Target({ElementType.ANNOTATION_TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@API(status = STABLE, since = "5.0")
@ArgumentsSource(EnumArgumentsProvider.class)
@Repeatable(EnumSources.class)
@interface EnumSource {
    /**
     * Enum class to use (defaults to first parameter type if enum)
     */
    Class<? extends Enum<?>> value() default Enum.class;
    
    /**
     * Specific enum constant names or regex patterns
     */
    String[] names() default {};
    
    /**
     * Selection mode for filtering enum constants
     */
    Mode mode() default INCLUDE;
    
    /**
     * Range start for enum constants (experimental)
     */
    @API(status = EXPERIMENTAL, since = "5.12")
    String from() default "";
    
    /**
     * Range end for enum constants (experimental)
     */
    @API(status = EXPERIMENTAL, since = "5.12")
    String to() default "";
    
    /**
     * Selection mode enum
     */
    enum Mode {
        /**
         * Include only specified names (default)
         */
        INCLUDE,
        
        /**
         * Exclude specified names
         */
        EXCLUDE,
        
        /**
         * Include names matching all patterns
         */
        MATCH_ALL,
        
        /**
         * Include names matching any pattern
         */
        MATCH_ANY,
        
        /**
         * Exclude names matching patterns
         */
        MATCH_NONE
    }
}

Usage Examples:

import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.EnumSource;

enum Planet {
    MERCURY, VENUS, EARTH, MARS, JUPITER, SATURN, URANUS, NEPTUNE
}

enum Status {
    ACTIVE, INACTIVE, PENDING, SUSPENDED
}

class EnumSourceExamples {

    // All enum constants
    @ParameterizedTest
    @EnumSource(Planet.class)
    void testAllPlanets(Planet planet) {
        assertNotNull(planet);
        assertNotNull(planet.name());
    }

    // Inferred enum type from parameter
    @ParameterizedTest
    @EnumSource
    void testInferredEnum(Status status) {
        assertNotNull(status);
    }

    // Specific enum constants
    @ParameterizedTest
    @EnumSource(value = Planet.class, names = {"EARTH", "MARS", "JUPITER"})
    void testSpecificPlanets(Planet planet) {
        assertTrue(planet == Planet.EARTH || 
                  planet == Planet.MARS || 
                  planet == Planet.JUPITER);
    }

    // Exclude specific constants
    @ParameterizedTest
    @EnumSource(value = Status.class, names = {"SUSPENDED"}, mode = EnumSource.Mode.EXCLUDE)
    void testActiveStatuses(Status status) {
        assertNotEquals(Status.SUSPENDED, status);
    }

    // Pattern matching - include
    @ParameterizedTest
    @EnumSource(value = Planet.class, names = {".*US$"}, mode = EnumSource.Mode.MATCH_ANY)
    void testPlanetsEndingWithUs(Planet planet) {
        // VENUS, URANUS
        assertTrue(planet.name().endsWith("US"));
    }

    // Pattern matching - exclude
    @ParameterizedTest
    @EnumSource(value = Planet.class, names = {"^M.*"}, mode = EnumSource.Mode.MATCH_NONE)
    void testPlanetsNotStartingWithM(Planet planet) {
        // All except MERCURY, MARS
        assertFalse(planet.name().startsWith("M"));
    }

    // Multiple patterns - match all
    @ParameterizedTest
    @EnumSource(value = Planet.class, names = {".*R.*", ".*N.*"}, mode = EnumSource.Mode.MATCH_ALL)
    void testPlanetsWithRAndN(Planet planet) {
        // SATURN, URANUS
        assertTrue(planet.name().contains("R") && planet.name().contains("N"));
    }

    // Range selection (experimental)
    @ParameterizedTest
    @EnumSource(value = Planet.class, from = "EARTH", to = "JUPITER")
    void testInnerPlanets(Planet planet) {
        // EARTH, MARS, JUPITER
        int ordinal = planet.ordinal();
        assertTrue(ordinal >= Planet.EARTH.ordinal() && 
                  ordinal <= Planet.JUPITER.ordinal());
    }
}

@MethodSource Annotation

Provides arguments from factory method return values with support for various return types.

/**
 * Provides arguments from factory method return values
 */
@Target({ElementType.ANNOTATION_TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@API(status = STABLE, since = "5.0")
@ArgumentsSource(MethodArgumentsProvider.class)
@Repeatable(MethodSources.class)
@interface MethodSource {
    /**
     * Factory method names (defaults to test method name if empty)
     */
    String[] value() default "";
}

Usage Examples:

import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;
import org.junit.jupiter.params.provider.Arguments;
import java.util.stream.Stream;
import java.util.*;

class MethodSourceExamples {

    // Method name matches test method name
    @ParameterizedTest
    @MethodSource
    void testWithNumbers(int number) {
        assertTrue(number > 0);
    }

    static Stream<Integer> testWithNumbers() {
        return Stream.of(1, 2, 3, 5, 8);
    }

    // Explicit method name
    @ParameterizedTest
    @MethodSource("stringProvider")
    void testWithStrings(String value) {
        assertNotNull(value);
        assertFalse(value.isEmpty());
    }

    static Stream<String> stringProvider() {
        return Stream.of("apple", "banana", "cherry");
    }

    // Multiple arguments using Arguments.of()
    @ParameterizedTest
    @MethodSource("userProvider")
    void testWithMultipleArgs(String name, int age, boolean active) {
        assertNotNull(name);
        assertTrue(age >= 0);
    }

    static Stream<Arguments> userProvider() {
        return Stream.of(
            Arguments.of("Alice", 25, true),
            Arguments.of("Bob", 30, false),
            Arguments.of("Charlie", 35, true)
        );
    }

    // Collection return type
    @ParameterizedTest
    @MethodSource("listProvider")
    void testWithList(String fruit) {
        assertNotNull(fruit);
    }

    static List<String> listProvider() {
        return Arrays.asList("apple", "banana", "cherry");
    }

    // Array return type
    @ParameterizedTest
    @MethodSource("arrayProvider")
    void testWithArray(int value) {
        assertTrue(value > 0);
    }

    static int[] arrayProvider() {
        return new int[]{1, 2, 3, 4, 5};
    }

    // Object array for multiple parameters
    @ParameterizedTest
    @MethodSource("objectArrayProvider")
    void testWithObjectArray(String name, double price) {
        assertNotNull(name);
        assertTrue(price > 0);
    }

    static Object[][] objectArrayProvider() {
        return new Object[][]{
            {"Apple", 1.50},
            {"Banana", 0.75},
            {"Cherry", 2.00}
        };
    }

    // Iterator return type
    @ParameterizedTest
    @MethodSource("iteratorProvider")
    void testWithIterator(String value) {
        assertNotNull(value);
    }

    static Iterator<String> iteratorProvider() {
        return Arrays.asList("one", "two", "three").iterator();
    }

    // Multiple method sources
    @ParameterizedTest
    @MethodSource({"positiveNumbers", "negativeNumbers"})
    void testWithMultipleSources(int number) {
        assertNotEquals(0, number);
    }

    static Stream<Integer> positiveNumbers() {
        return Stream.of(1, 2, 3);
    }

    static Stream<Integer> negativeNumbers() {
        return Stream.of(-1, -2, -3);
    }

    // External class method source
    @ParameterizedTest
    @MethodSource("com.example.TestDataProvider#providePairs")
    void testWithExternalSource(String key, String value) {
        assertNotNull(key);
        assertNotNull(value);
    }

    // Complex data structures
    @ParameterizedTest
    @MethodSource("complexDataProvider")
    void testWithComplexData(Map<String, Object> data) {
        assertNotNull(data);
        assertFalse(data.isEmpty());
    }

    static Stream<Map<String, Object>> complexDataProvider() {
        return Stream.of(
            Map.of("name", "Product A", "price", 19.99, "available", true),
            Map.of("name", "Product B", "price", 29.50, "available", false)
        );
    }
}

@FieldSource Annotation

Provides arguments from field values (experimental feature since JUnit 5.11).

/**
 * Provides arguments from field values (experimental)
 */
@Target({ElementType.ANNOTATION_TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@API(status = EXPERIMENTAL, since = "5.11")
@ArgumentsSource(FieldArgumentsProvider.class)
@Repeatable(FieldSources.class)
@interface FieldSource {
    /**
     * Field names (defaults to test method name if empty)
     */
    String[] value() default "";
}

Usage Examples:

import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.FieldSource;
import org.junit.jupiter.params.provider.Arguments;
import java.util.function.Supplier;
import java.util.stream.Stream;
import java.util.*;

class FieldSourceExamples {

    // Static field with same name as test method
    static List<String> testWithFieldData = Arrays.asList("apple", "banana", "cherry");

    @ParameterizedTest
    @FieldSource
    void testWithFieldData(String fruit) {
        assertNotNull(fruit);
    }

    // Explicit field name
    static int[] numbers = {1, 2, 3, 5, 8};

    @ParameterizedTest
    @FieldSource("numbers")
    void testWithNumbers(int number) {
        assertTrue(number > 0);
    }

    // Field containing Arguments
    static List<Arguments> userTestData = Arrays.asList(
        Arguments.of("Alice", 25, true),
        Arguments.of("Bob", 30, false),
        Arguments.of("Charlie", 35, true)
    );

    @ParameterizedTest
    @FieldSource("userTestData")
    void testWithUserData(String name, int age, boolean active) {
        assertNotNull(name);
        assertTrue(age >= 0);
    }

    // Supplier field for lazy evaluation
    static Supplier<Stream<String>> lazyStringProvider = () -> 
        Stream.of("lazy1", "lazy2", "lazy3");

    @ParameterizedTest
    @FieldSource("lazyStringProvider")
    void testWithLazyField(String value) {
        assertNotNull(value);
        assertTrue(value.startsWith("lazy"));
    }

    // Multiple fields
    static List<String> fruits = Arrays.asList("apple", "banana");
    static List<String> vegetables = Arrays.asList("carrot", "broccoli");

    @ParameterizedTest
    @FieldSource({"fruits", "vegetables"})
    void testWithMultipleFields(String item) {
        assertNotNull(item);
    }

    // External class field
    @ParameterizedTest
    @FieldSource("com.example.TestData#testValues")
    void testWithExternalField(String value) {
        assertNotNull(value);
    }
}

Container Annotations

Container annotations for multiple enum and method source annotations.

/**
 * Container annotation for multiple @EnumSource annotations
 */
@Target({ElementType.ANNOTATION_TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@API(status = STABLE, since = "5.0")
@interface EnumSources {
    EnumSource[] value();
}

/**
 * Container annotation for multiple @MethodSource annotations
 */
@Target({ElementType.ANNOTATION_TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@API(status = STABLE, since = "5.0")
@interface MethodSources {
    MethodSource[] value();
}

/**
 * Container annotation for multiple @FieldSource annotations
 */
@Target({ElementType.ANNOTATION_TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@API(status = EXPERIMENTAL, since = "5.11")
@interface FieldSources {
    FieldSource[] value();
}

Advanced Patterns

Complex Method Source Patterns:

class AdvancedMethodSourceExamples {

    // Parameterized test with test case names
    @ParameterizedTest(name = "Test case: {0}")
    @MethodSource("namedTestCases")
    void testWithNamedCases(String testCase, int input, int expected) {
        // Test implementation using testCase description
        assertNotNull(testCase);
        assertTrue(input >= 0);
        assertTrue(expected >= 0);
    }

    static Stream<Arguments> namedTestCases() {
        return Stream.of(
            Arguments.of("Square root of 4", 4, 2),
            Arguments.of("Square root of 9", 9, 3),
            Arguments.of("Square root of 16", 16, 4)
        );
    }

    // Dynamic data generation
    @ParameterizedTest
    @MethodSource("dynamicDataProvider")
    void testWithDynamicData(int value) {
        assertTrue(value > 0);
    }

    static Stream<Integer> dynamicDataProvider() {
        return Stream.iterate(1, n -> n < 100, n -> n * 2);
    }

    // Combining different data sources
    @ParameterizedTest
    @MethodSource("combinedDataProvider")
    void testWithCombinedData(String type, Object value) {
        assertNotNull(type);
        assertNotNull(value);
    }

    static Stream<Arguments> combinedDataProvider() {
        return Stream.concat(
            Stream.of("string").map(s -> Arguments.of("String", s)),
            Stream.of(42).map(i -> Arguments.of("Integer", i))
        );
    }
}

These advanced source types provide powerful capabilities for data-driven testing, enabling complex test scenarios with enum-based logic, dynamic data generation, and external data sources.

Install with Tessl CLI

npx tessl i tessl/maven-org-junit-jupiter--junit-jupiter-params

docs

argument-aggregation.md

argument-conversion.md

core-testing.md

csv-sources.md

custom-sources.md

enum-method-sources.md

index.md

value-sources.md

tile.json