diff --git a/testing-modules/junit-5/pom.xml b/testing-modules/junit-5/pom.xml
index b7600267d9..a5a1ddaf0b 100644
--- a/testing-modules/junit-5/pom.xml
+++ b/testing-modules/junit-5/pom.xml
@@ -21,6 +21,11 @@
junit-platform-engine
${junit.platform.version}
+
+ org.junit.jupiter
+ junit-jupiter-params
+ ${junit.jupiter.version}
+
org.junit.platform
junit-platform-runner
diff --git a/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/BlankStringsArgumentsProvider.java b/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/BlankStringsArgumentsProvider.java
new file mode 100644
index 0000000000..1d2c76d37b
--- /dev/null
+++ b/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/BlankStringsArgumentsProvider.java
@@ -0,0 +1,19 @@
+package com.baeldung.parameterized;
+
+import org.junit.jupiter.api.extension.ExtensionContext;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.ArgumentsProvider;
+
+import java.util.stream.Stream;
+
+class BlankStringsArgumentsProvider implements ArgumentsProvider {
+
+ @Override
+ public Stream extends Arguments> provideArguments(ExtensionContext context) {
+ return Stream.of(
+ Arguments.of((String) null),
+ Arguments.of(""),
+ Arguments.of(" ")
+ );
+ }
+}
diff --git a/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/EnumsUnitTest.java b/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/EnumsUnitTest.java
new file mode 100644
index 0000000000..0b2068dbf1
--- /dev/null
+++ b/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/EnumsUnitTest.java
@@ -0,0 +1,50 @@
+package com.baeldung.parameterized;
+
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.CsvSource;
+import org.junit.jupiter.params.provider.EnumSource;
+
+import java.time.Month;
+import java.util.EnumSet;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+class EnumsUnitTest {
+
+ @ParameterizedTest
+ @EnumSource(Month.class)
+ void getValueForAMonth_IsAlwaysBetweenOneAndTwelve(Month month) {
+ int monthNumber = month.getValue();
+ assertTrue(monthNumber >= 1 && monthNumber <= 12);
+ }
+
+ @ParameterizedTest(name = "{index} {0} is 30 days long")
+ @EnumSource(value = Month.class, names = {"APRIL", "JUNE", "SEPTEMBER", "NOVEMBER"})
+ void someMonths_Are30DaysLong(Month month) {
+ final boolean isALeapYear = false;
+ assertEquals(30, month.length(isALeapYear));
+ }
+
+ @ParameterizedTest
+ @EnumSource(value = Month.class, names = {"APRIL", "JUNE", "SEPTEMBER", "NOVEMBER", "FEBRUARY"}, mode = EnumSource.Mode.EXCLUDE)
+ void exceptFourMonths_OthersAre31DaysLong(Month month) {
+ final boolean isALeapYear = false;
+ assertEquals(31, month.length(isALeapYear));
+ }
+
+ @ParameterizedTest
+ @EnumSource(value = Month.class, names = ".+BER", mode = EnumSource.Mode.MATCH_ANY)
+ void fourMonths_AreEndingWithBer(Month month) {
+ EnumSet months = EnumSet.of(Month.SEPTEMBER, Month.OCTOBER, Month.NOVEMBER, Month.DECEMBER);
+ assertTrue(months.contains(month));
+ }
+
+ @ParameterizedTest
+ @CsvSource({"APRIL", "JUNE", "SEPTEMBER", "NOVEMBER"})
+ void someMonths_Are30DaysLongCsv(Month month) {
+ final boolean isALeapYear = false;
+ assertEquals(30, month.length(isALeapYear));
+ }
+
+}
diff --git a/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/LocalDateUnitTest.java b/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/LocalDateUnitTest.java
new file mode 100644
index 0000000000..95487705f5
--- /dev/null
+++ b/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/LocalDateUnitTest.java
@@ -0,0 +1,18 @@
+package com.baeldung.parameterized;
+
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.converter.ConvertWith;
+import org.junit.jupiter.params.provider.CsvSource;
+
+import java.time.LocalDate;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class LocalDateUnitTest {
+
+ @ParameterizedTest
+ @CsvSource({"2018/12/25,2018", "2019/02/11,2019"})
+ void getYear_ShouldWorkAsExpected(@ConvertWith(SlashyDateConverter.class) LocalDate date, int expected) {
+ assertEquals(expected, date.getYear());
+ }
+}
diff --git a/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/Numbers.java b/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/Numbers.java
new file mode 100644
index 0000000000..8a9b229aac
--- /dev/null
+++ b/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/Numbers.java
@@ -0,0 +1,8 @@
+package com.baeldung.parameterized;
+
+public class Numbers {
+
+ public static boolean isOdd(int number) {
+ return number % 2 != 0;
+ }
+}
diff --git a/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/NumbersUnitTest.java b/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/NumbersUnitTest.java
new file mode 100644
index 0000000000..b3a3371bb2
--- /dev/null
+++ b/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/NumbersUnitTest.java
@@ -0,0 +1,15 @@
+package com.baeldung.parameterized;
+
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.ValueSource;
+
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+class NumbersUnitTest {
+
+ @ParameterizedTest
+ @ValueSource(ints = {1, 3, 5, -3, 15, Integer.MAX_VALUE})
+ void isOdd_ShouldReturnTrueForOddNumbers(int number) {
+ assertTrue(Numbers.isOdd(number));
+ }
+}
\ No newline at end of file
diff --git a/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/Person.java b/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/Person.java
new file mode 100644
index 0000000000..225f11ba29
--- /dev/null
+++ b/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/Person.java
@@ -0,0 +1,20 @@
+package com.baeldung.parameterized;
+
+class Person {
+
+ private final String firstName;
+ private final String middleName;
+ private final String lastName;
+
+ public Person(String firstName, String middleName, String lastName) {
+ this.firstName = firstName;
+ this.middleName = middleName;
+ this.lastName = lastName;
+ }
+
+ public String fullName() {
+ if (middleName == null || middleName.trim().isEmpty()) return String.format("%s %s", firstName, lastName);
+
+ return String.format("%s %s %s", firstName, middleName, lastName);
+ }
+}
diff --git a/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/PersonAggregator.java b/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/PersonAggregator.java
new file mode 100644
index 0000000000..df2ddc9e66
--- /dev/null
+++ b/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/PersonAggregator.java
@@ -0,0 +1,15 @@
+package com.baeldung.parameterized;
+
+import org.junit.jupiter.api.extension.ParameterContext;
+import org.junit.jupiter.params.aggregator.ArgumentsAccessor;
+import org.junit.jupiter.params.aggregator.ArgumentsAggregationException;
+import org.junit.jupiter.params.aggregator.ArgumentsAggregator;
+
+class PersonAggregator implements ArgumentsAggregator {
+
+ @Override
+ public Object aggregateArguments(ArgumentsAccessor accessor, ParameterContext context)
+ throws ArgumentsAggregationException {
+ return new Person(accessor.getString(1), accessor.getString(2), accessor.getString(3));
+ }
+}
diff --git a/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/PersonUnitTest.java b/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/PersonUnitTest.java
new file mode 100644
index 0000000000..b30ecc748e
--- /dev/null
+++ b/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/PersonUnitTest.java
@@ -0,0 +1,31 @@
+package com.baeldung.parameterized;
+
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.aggregator.AggregateWith;
+import org.junit.jupiter.params.aggregator.ArgumentsAccessor;
+import org.junit.jupiter.params.provider.CsvSource;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class PersonUnitTest {
+
+ @ParameterizedTest
+ @CsvSource({"Isaac,,Newton, Isaac Newton", "Charles,Robert,Darwin,Charles Robert Darwin"})
+ void fullName_ShouldGenerateTheExpectedFullName(ArgumentsAccessor argumentsAccessor) {
+ String firstName = argumentsAccessor.getString(0);
+ String middleName = (String) argumentsAccessor.get(1);
+ String lastName = argumentsAccessor.get(2, String.class);
+ String expectedFullName = argumentsAccessor.getString(3);
+
+ Person person = new Person(firstName, middleName, lastName);
+ assertEquals(expectedFullName, person.fullName());
+ }
+
+ @ParameterizedTest
+ @CsvSource({"Isaac Newton,Isaac,,Newton", "Charles Robert Darwin,Charles,Robert,Darwin"})
+ void fullName_ShouldGenerateTheExpectedFullName(String expectedFullName,
+ @AggregateWith(PersonAggregator.class) Person person) {
+
+ assertEquals(expectedFullName, person.fullName());
+ }
+}
diff --git a/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/SlashyDateConverter.java b/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/SlashyDateConverter.java
new file mode 100644
index 0000000000..40773d29a9
--- /dev/null
+++ b/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/SlashyDateConverter.java
@@ -0,0 +1,27 @@
+package com.baeldung.parameterized;
+
+import org.junit.jupiter.api.extension.ParameterContext;
+import org.junit.jupiter.params.converter.ArgumentConversionException;
+import org.junit.jupiter.params.converter.ArgumentConverter;
+
+import java.time.LocalDate;
+
+class SlashyDateConverter implements ArgumentConverter {
+
+ @Override
+ public Object convert(Object source, ParameterContext context) throws ArgumentConversionException {
+ if (!(source instanceof String))
+ throw new IllegalArgumentException("The argument should be a string: " + source);
+
+ try {
+ String[] parts = ((String) source).split("/");
+ int year = Integer.parseInt(parts[0]);
+ int month = Integer.parseInt(parts[1]);
+ int day = Integer.parseInt(parts[2]);
+
+ return LocalDate.of(year, month, day);
+ } catch (Exception e) {
+ throw new IllegalArgumentException("Failed to convert", e);
+ }
+ }
+}
diff --git a/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/StringParams.java b/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/StringParams.java
new file mode 100644
index 0000000000..bc9f881bd4
--- /dev/null
+++ b/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/StringParams.java
@@ -0,0 +1,10 @@
+package com.baeldung.parameterized;
+
+import java.util.stream.Stream;
+
+public class StringParams {
+
+ static Stream blankStrings() {
+ return Stream.of(null, "", " ");
+ }
+}
diff --git a/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/Strings.java b/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/Strings.java
new file mode 100644
index 0000000000..f8e29f6b7f
--- /dev/null
+++ b/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/Strings.java
@@ -0,0 +1,8 @@
+package com.baeldung.parameterized;
+
+class Strings {
+
+ static boolean isBlank(String input) {
+ return input == null || input.trim().isEmpty();
+ }
+}
diff --git a/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/StringsUnitTest.java b/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/StringsUnitTest.java
new file mode 100644
index 0000000000..7d02a5a74b
--- /dev/null
+++ b/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/StringsUnitTest.java
@@ -0,0 +1,108 @@
+package com.baeldung.parameterized;
+
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.*;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Stream;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+class StringsUnitTest {
+
+ static Stream arguments = Stream.of(
+ Arguments.of(null, true), // null strings should be considered blank
+ Arguments.of("", true),
+ Arguments.of(" ", true),
+ Arguments.of("not blank", false)
+ );
+
+ @ParameterizedTest
+ @VariableSource("arguments")
+ void isBlank_ShouldReturnTrueForNullOrBlankStringsVariableSource(String input, boolean expected) {
+ assertEquals(expected, Strings.isBlank(input));
+ }
+
+ @ParameterizedTest
+ @ValueSource(strings = {"", " "})
+ void isBlank_ShouldReturnTrueForNullOrBlankStrings(String input) {
+ assertTrue(Strings.isBlank(input));
+ }
+
+ @ParameterizedTest
+ @MethodSource("provideStringsForIsBlank")
+ void isBlank_ShouldReturnTrueForNullOrBlankStrings(String input, boolean expected) {
+ assertEquals(expected, Strings.isBlank(input));
+ }
+
+ @ParameterizedTest
+ @MethodSource // Please note method name is not provided
+ void isBlank_ShouldReturnTrueForNullOrBlankStringsOneArgument(String input) {
+ assertTrue(Strings.isBlank(input));
+ }
+
+ @ParameterizedTest
+ @MethodSource("com.baeldung.parameterized.StringParams#blankStrings")
+ void isBlank_ShouldReturnTrueForNullOrBlankStringsExternalSource(String input) {
+ assertTrue(Strings.isBlank(input));
+ }
+
+ @ParameterizedTest
+ @ArgumentsSource(BlankStringsArgumentsProvider.class)
+ void isBlank_ShouldReturnTrueForNullOrBlankStringsArgProvider(String input) {
+ assertTrue(Strings.isBlank(input));
+ }
+
+ private static Stream isBlank_ShouldReturnTrueForNullOrBlankStringsOneArgument() {
+ return Stream.of(null, "", " ");
+ }
+
+ @ParameterizedTest
+ @MethodSource("provideStringsForIsBlankList")
+ void isBlank_ShouldReturnTrueForNullOrBlankStringsList(String input, boolean expected) {
+ assertEquals(expected, Strings.isBlank(input));
+ }
+
+ @ParameterizedTest
+ @CsvSource({"test,TEST", "tEst,TEST", "Java,JAVA"}) // Passing a CSV pair per test execution
+ void toUpperCase_ShouldGenerateTheExpectedUppercaseValue(String input, String expected) {
+ String actualValue = input.toUpperCase();
+ assertEquals(expected, actualValue);
+ }
+
+ @ParameterizedTest
+ @CsvSource(value = {"test:test", "tEst:test", "Java:java"}, delimiter =':') // Using : as the column separator.
+ void toLowerCase_ShouldGenerateTheExpectedLowercaseValue(String input, String expected) {
+ String actualValue = input.toLowerCase();
+ assertEquals(expected, actualValue);
+ }
+
+ @ParameterizedTest
+ @CsvFileSource(resources = "/data.csv", numLinesToSkip = 1)
+ void toUpperCase_ShouldGenerateTheExpectedUppercaseValueCSVFile(String input, String expected) {
+ String actualValue = input.toUpperCase();
+ assertEquals(expected, actualValue);
+ }
+
+
+
+ private static Stream provideStringsForIsBlank() {
+ return Stream.of(
+ Arguments.of(null, true), // null strings should be considered blank
+ Arguments.of("", true),
+ Arguments.of(" ", true),
+ Arguments.of("not blank", false)
+ );
+ }
+
+ private static List provideStringsForIsBlankList() {
+ return Arrays.asList(
+ Arguments.of(null, true), // null strings should be considered blank
+ Arguments.of("", true),
+ Arguments.of(" ", true),
+ Arguments.of("not blank", false)
+ );
+ }
+}
\ No newline at end of file
diff --git a/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/VariableArgumentsProvider.java b/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/VariableArgumentsProvider.java
new file mode 100644
index 0000000000..a96d01e854
--- /dev/null
+++ b/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/VariableArgumentsProvider.java
@@ -0,0 +1,45 @@
+package com.baeldung.parameterized;
+
+import org.junit.jupiter.api.extension.ExtensionContext;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.ArgumentsProvider;
+import org.junit.jupiter.params.support.AnnotationConsumer;
+
+import java.lang.reflect.Field;
+import java.util.stream.Stream;
+
+class VariableArgumentsProvider implements ArgumentsProvider, AnnotationConsumer {
+
+ private String variableName;
+
+ @Override
+ public Stream extends Arguments> provideArguments(ExtensionContext context) {
+ return context.getTestClass()
+ .map(this::getField)
+ .map(this::getValue)
+ .orElseThrow(() -> new IllegalArgumentException("Failed to load test arguments"));
+ }
+
+ @Override
+ public void accept(VariableSource variableSource) {
+ variableName = variableSource.value();
+ }
+
+ private Field getField(Class> clazz) {
+ try {
+ return clazz.getDeclaredField(variableName);
+ } catch (Exception e) {
+ return null;
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ private Stream getValue(Field field) {
+ Object value = null;
+ try {
+ value = field.get(null);
+ } catch (Exception ignored) {}
+
+ return value == null ? null : (Stream) value;
+ }
+}
diff --git a/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/VariableSource.java b/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/VariableSource.java
new file mode 100644
index 0000000000..9c1d07c1be
--- /dev/null
+++ b/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/VariableSource.java
@@ -0,0 +1,19 @@
+package com.baeldung.parameterized;
+
+import org.junit.jupiter.params.provider.ArgumentsSource;
+
+import java.lang.annotation.*;
+
+@Documented
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+@ArgumentsSource(VariableArgumentsProvider.class)
+public @interface VariableSource {
+
+ /**
+ * Represents the name of the static variable to load the test arguments from.
+ *
+ * @return Static variable name.
+ */
+ String value();
+}
diff --git a/testing-modules/junit-5/src/test/resources/data.csv b/testing-modules/junit-5/src/test/resources/data.csv
new file mode 100644
index 0000000000..321554cc23
--- /dev/null
+++ b/testing-modules/junit-5/src/test/resources/data.csv
@@ -0,0 +1,4 @@
+input,expected
+test,TEST
+tEst,TEST
+Java,JAVA
\ No newline at end of file