From adb59baee45a0db53779c9f399bd697d04b4d430 Mon Sep 17 00:00:00 2001 From: Clemens L Date: Thu, 19 Sep 2024 15:05:00 +0200 Subject: [PATCH] Allow nullable Java Time parameters Issue: #4010 --- .../converter/JavaTimeArgumentConverter.java | 6 +++++- .../converter/JavaTimeConversionPattern.java | 5 +++++ .../JavaTimeArgumentConverterTests.java | 19 +++++++++++++++++++ 3 files changed, 29 insertions(+), 1 deletion(-) diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/converter/JavaTimeArgumentConverter.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/converter/JavaTimeArgumentConverter.java index 26fe98e29df0..e4f75c5d651b 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/converter/JavaTimeArgumentConverter.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/converter/JavaTimeArgumentConverter.java @@ -52,7 +52,11 @@ class JavaTimeArgumentConverter extends AnnotationBasedArgumentConverter targetClass, JavaTimeConversionPattern annotation) { if (input == null) { - throw new ArgumentConversionException("Cannot convert null to " + targetClass.getName()); + if (annotation.nullable()) { + return null; + } + throw new ArgumentConversionException( + "Cannot convert null to " + targetClass.getName() + ", consider setting 'nullable = true'"); } TemporalQuery temporalQuery = TEMPORAL_QUERIES.get(targetClass); if (temporalQuery == null) { diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/converter/JavaTimeConversionPattern.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/converter/JavaTimeConversionPattern.java index d5ec9d509453..c2cbf8b5c1d5 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/converter/JavaTimeConversionPattern.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/converter/JavaTimeConversionPattern.java @@ -45,4 +45,9 @@ */ String value(); + /** + * Whether this Java Time parameter may be null or not. + */ + boolean nullable() default false; + } diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/params/converter/JavaTimeArgumentConverterTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/params/converter/JavaTimeArgumentConverterTests.java index 3983886cd476..78231d795980 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/params/converter/JavaTimeArgumentConverterTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/params/converter/JavaTimeArgumentConverterTests.java @@ -110,10 +110,29 @@ void throwsExceptionOnInvalidTargetType() { assertThat(exception).hasMessage("Cannot convert to java.lang.Integer: 2017"); } + @Test + void throwsExceptionOnNullParameterWithoutNullable() { + var exception = assertThrows(ArgumentConversionException.class, + () -> convert(null, "dd.MM.yyyy", LocalDate.class)); + + assertThat(exception).hasMessage( + "Cannot convert null to java.time.LocalDate, consider setting 'nullable = true'"); + } + + @Test + void convertsNullableParameter() { + assertThat(convert(null, "dd.MM.yyyy", true, LocalDate.class)).isEqualTo(null); + } + private Object convert(Object input, String pattern, Class targetClass) { + return convert(input, pattern, false, targetClass); + } + + private Object convert(Object input, String pattern, boolean nullable, Class targetClass) { var converter = new JavaTimeArgumentConverter(); var annotation = mock(JavaTimeConversionPattern.class); when(annotation.value()).thenReturn(pattern); + when(annotation.nullable()).thenReturn(nullable); return converter.convert(input, targetClass, annotation); }