From d56d2c7a74d5f71e9641aeecdda2a5d7f9500759 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Thu, 1 May 2025 12:30:22 +0100 Subject: [PATCH] Test unit annotations that affect property binding --- .../ConfigPropsApplicationAotTests.java | 66 ++++++++++++++++++- .../java/com/example/configprops/CLR.java | 17 ++++- .../configprops/ctor/AppPropertiesCtor.java | 41 ++++++++++-- .../configprops/javabean/AppProperties.java | 45 ++++++++++++- .../records/AppPropertiesRecord.java | 13 +++- .../src/main/resources/application.yaml | 9 +++ 6 files changed, 177 insertions(+), 14 deletions(-) diff --git a/boot/configuration-properties/src/appTest/java/com/example/configprops/ConfigPropsApplicationAotTests.java b/boot/configuration-properties/src/appTest/java/com/example/configprops/ConfigPropsApplicationAotTests.java index 01cf6f32..e2281533 100644 --- a/boot/configuration-properties/src/appTest/java/com/example/configprops/ConfigPropsApplicationAotTests.java +++ b/boot/configuration-properties/src/appTest/java/com/example/configprops/ConfigPropsApplicationAotTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2022-2024 the original author or authors. + * Copyright 2022-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -47,6 +47,27 @@ class ConfigPropsApplicationAotTests { }); } + @Test + void dataSizeWithCustomDefaultUnitShouldBind(AssertableOutput output) { + Awaitility.await().atMost(Duration.ofSeconds(10)).untilAsserted(() -> { + assertThat(output).hasSingleLineContaining("appProperties.getCustomDefaultUnitDataSize(): 5242880B"); + }); + } + + @Test + void durationShouldBind(AssertableOutput output) { + Awaitility.await().atMost(Duration.ofSeconds(10)).untilAsserted(() -> { + assertThat(output).hasSingleLineContaining("appProperties.getDuration(): PT30S"); + }); + } + + @Test + void durationWithCustomDefaultUnitShouldBind(AssertableOutput output) { + Awaitility.await().atMost(Duration.ofSeconds(10)).untilAsserted(() -> { + assertThat(output).hasSingleLineContaining("appProperties.getCustomDefaultUnitDuration(): PT10M"); + }); + } + @Test void stringListShouldBind(AssertableOutput output) { Awaitility.await().atMost(Duration.ofSeconds(10)).untilAsserted(() -> { @@ -124,6 +145,28 @@ class ConfigPropsApplicationAotTests { }); } + @Test + void dataSizeWithCustomDefaultUnitShouldBind(AssertableOutput output) { + Awaitility.await().atMost(Duration.ofSeconds(10)).untilAsserted(() -> { + assertThat(output) + .hasSingleLineContaining("appPropertiesCtor.getCustomDefaultUnitDataSize(): 5242880B"); + }); + } + + @Test + void durationShouldBind(AssertableOutput output) { + Awaitility.await().atMost(Duration.ofSeconds(10)).untilAsserted(() -> { + assertThat(output).hasSingleLineContaining("appPropertiesCtor.getDuration(): PT30S"); + }); + } + + @Test + void durationWithCustomDefaultUnitShouldBind(AssertableOutput output) { + Awaitility.await().atMost(Duration.ofSeconds(10)).untilAsserted(() -> { + assertThat(output).hasSingleLineContaining("appPropertiesCtor.getCustomDefaultUnitDuration(): PT10M"); + }); + } + @Test void stringListShouldBind(AssertableOutput output) { Awaitility.await().atMost(Duration.ofSeconds(10)).untilAsserted(() -> { @@ -187,6 +230,27 @@ class ConfigPropsApplicationAotTests { }); } + @Test + void dataSizeWithCustomDefaultUnitShouldBind(AssertableOutput output) { + Awaitility.await().atMost(Duration.ofSeconds(10)).untilAsserted(() -> { + assertThat(output).hasSingleLineContaining("appPropertiesRecord.customDefaultUnitDataSize(): 5242880B"); + }); + } + + @Test + void durationShouldBind(AssertableOutput output) { + Awaitility.await().atMost(Duration.ofSeconds(10)).untilAsserted(() -> { + assertThat(output).hasSingleLineContaining("appPropertiesRecord.duration(): PT30S"); + }); + } + + @Test + void durationWithCustomDefaultUnitShouldBind(AssertableOutput output) { + Awaitility.await().atMost(Duration.ofSeconds(10)).untilAsserted(() -> { + assertThat(output).hasSingleLineContaining("appPropertiesRecord.customDefaultUnitDuration(): PT10M"); + }); + } + @Test void stringListShouldBind(AssertableOutput output) { Awaitility.await().atMost(Duration.ofSeconds(10)).untilAsserted(() -> { diff --git a/boot/configuration-properties/src/main/java/com/example/configprops/CLR.java b/boot/configuration-properties/src/main/java/com/example/configprops/CLR.java index e9ecd22a..3fdadc41 100644 --- a/boot/configuration-properties/src/main/java/com/example/configprops/CLR.java +++ b/boot/configuration-properties/src/main/java/com/example/configprops/CLR.java @@ -1,5 +1,5 @@ /* - * Copyright 2022-2024 the original author or authors. + * Copyright 2022-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -49,6 +49,11 @@ public class CLR implements CommandLineRunner { public void run(String... args) throws Exception { System.out.printf("appProperties.getString(): %s%n", appProperties.getString()); System.out.printf("appProperties.getDataSize(): %s%n", appProperties.getDataSize()); + System.out.printf("appProperties.getCustomDefaultUnitDataSize(): %s%n", + appProperties.getCustomDefaultUnitDataSize()); + System.out.printf("appProperties.getDuration(): %s%n", appProperties.getDuration()); + System.out.printf("appProperties.getCustomDefaultUnitDuration(): %s%n", + appProperties.getCustomDefaultUnitDuration()); System.out.printf("appProperties.getStringList(): %s%n", appProperties.getStringList()); System.out.printf("appProperties.getNestedList(): %s%n", appProperties.getNestedList()); System.out.printf("appProperties.getStringMap(): %s%n", appProperties.getStringMap()); @@ -61,6 +66,11 @@ public class CLR implements CommandLineRunner { System.out.printf("appPropertiesCtor.getString(): %s%n", appPropertiesCtor.getString()); System.out.printf("appPropertiesCtor.getDataSize(): %s%n", appPropertiesCtor.getDataSize()); + System.out.printf("appPropertiesCtor.getCustomDefaultUnitDataSize(): %s%n", + appPropertiesCtor.getCustomDefaultUnitDataSize()); + System.out.printf("appPropertiesCtor.getDuration(): %s%n", appPropertiesCtor.getDuration()); + System.out.printf("appPropertiesCtor.getCustomDefaultUnitDuration(): %s%n", + appPropertiesCtor.getCustomDefaultUnitDuration()); System.out.printf("appPropertiesCtor.getStringList(): %s%n", appPropertiesCtor.getStringList()); System.out.printf("appPropertiesCtor.getNestedList(): %s%n", appPropertiesCtor.getNestedList()); System.out.printf("appPropertiesCtor.getNested(): %s%n", appPropertiesCtor.getNested()); @@ -71,6 +81,11 @@ public class CLR implements CommandLineRunner { System.out.printf("appPropertiesRecord.string(): %s%n", appPropertiesRecord.string()); System.out.printf("appPropertiesRecord.dataSize(): %s%n", appPropertiesRecord.dataSize()); + System.out.printf("appPropertiesRecord.customDefaultUnitDataSize(): %s%n", + appPropertiesRecord.customDefaultUnitDataSize()); + System.out.printf("appPropertiesRecord.duration(): %s%n", appPropertiesRecord.duration()); + System.out.printf("appPropertiesRecord.customDefaultUnitDuration(): %s%n", + appPropertiesRecord.customDefaultUnitDuration()); System.out.printf("appPropertiesRecord.stringList(): %s%n", appPropertiesRecord.stringList()); System.out.printf("appPropertiesRecord.nestedList(): %s%n", appPropertiesRecord.nestedList()); System.out.printf("appPropertiesRecord.nested(): %s%n", appPropertiesRecord.nested()); diff --git a/boot/configuration-properties/src/main/java/com/example/configprops/ctor/AppPropertiesCtor.java b/boot/configuration-properties/src/main/java/com/example/configprops/ctor/AppPropertiesCtor.java index a60b43ab..9c421a3e 100644 --- a/boot/configuration-properties/src/main/java/com/example/configprops/ctor/AppPropertiesCtor.java +++ b/boot/configuration-properties/src/main/java/com/example/configprops/ctor/AppPropertiesCtor.java @@ -1,5 +1,5 @@ /* - * Copyright 2022-2024 the original author or authors. + * Copyright 2022-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,11 +16,16 @@ package com.example.configprops.ctor; +import java.time.Duration; +import java.time.temporal.ChronoUnit; import java.util.List; +import org.springframework.boot.convert.DataSizeUnit; +import org.springframework.boot.convert.DurationUnit; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.NestedConfigurationProperty; import org.springframework.util.unit.DataSize; +import org.springframework.util.unit.DataUnit; @ConfigurationProperties(prefix = "app.ctor") public class AppPropertiesCtor { @@ -29,6 +34,12 @@ public class AppPropertiesCtor { private final DataSize dataSize; + private final DataSize customDefaultUnitDataSize; + + private final Duration duration; + + private final Duration customDefaultUnitDuration; + private final List stringList; private final List nestedList; @@ -38,10 +49,15 @@ public class AppPropertiesCtor { @NestedConfigurationProperty private final NestedNotInner nestedNotInner; - public AppPropertiesCtor(String string, DataSize dataSize, List stringList, List nestedList, - Nested nested, NestedNotInner nestedNotInner) { + public AppPropertiesCtor(String string, DataSize dataSize, + @DataSizeUnit(DataUnit.MEGABYTES) DataSize customDefaultUnitDataSize, Duration duration, + @DurationUnit(ChronoUnit.MINUTES) Duration customDefaultUnitDuration, List stringList, + List nestedList, Nested nested, NestedNotInner nestedNotInner) { this.string = string; this.dataSize = dataSize; + this.customDefaultUnitDataSize = customDefaultUnitDataSize; + this.duration = duration; + this.customDefaultUnitDuration = customDefaultUnitDuration; this.stringList = stringList; this.nestedList = nestedList; this.nested = nested; @@ -56,6 +72,18 @@ public class AppPropertiesCtor { return dataSize; } + public DataSize getCustomDefaultUnitDataSize() { + return customDefaultUnitDataSize; + } + + public Duration getDuration() { + return duration; + } + + public Duration getCustomDefaultUnitDuration() { + return customDefaultUnitDuration; + } + public List getStringList() { return stringList; } @@ -74,9 +102,10 @@ public class AppPropertiesCtor { @Override public String toString() { - return "AppPropertiesCtor{" + "string='" + string + '\'' + ", dataSize=" + dataSize + ", stringList=" - + stringList + ", nestedList=" + nestedList + ", nested=" + nested + ", nestedNotInner=" - + nestedNotInner + '}'; + return "AppPropertiesCtor{" + "string='" + string + '\'' + ", dataSize=" + dataSize + + ", customDefaultUnitDataSize=" + customDefaultUnitDataSize + ", duration=" + duration + + ", customDefaultUnitDuration=" + customDefaultUnitDuration + ", stringList=" + stringList + + ", nestedList=" + nestedList + ", nested=" + nested + ", nestedNotInner=" + nestedNotInner + '}'; } public static class Nested { diff --git a/boot/configuration-properties/src/main/java/com/example/configprops/javabean/AppProperties.java b/boot/configuration-properties/src/main/java/com/example/configprops/javabean/AppProperties.java index 12e60ee9..ab0d5459 100644 --- a/boot/configuration-properties/src/main/java/com/example/configprops/javabean/AppProperties.java +++ b/boot/configuration-properties/src/main/java/com/example/configprops/javabean/AppProperties.java @@ -1,5 +1,5 @@ /* - * Copyright 2022-2024 the original author or authors. + * Copyright 2022-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,14 +16,19 @@ package com.example.configprops.javabean; +import java.time.Duration; +import java.time.temporal.ChronoUnit; import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import org.springframework.boot.convert.DataSizeUnit; +import org.springframework.boot.convert.DurationUnit; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.NestedConfigurationProperty; import org.springframework.util.unit.DataSize; +import org.springframework.util.unit.DataUnit; @ConfigurationProperties(prefix = "app") public class AppProperties { @@ -32,6 +37,14 @@ public class AppProperties { private DataSize dataSize; + @DataSizeUnit(DataUnit.MEGABYTES) + private DataSize customDefaultUnitDataSize; + + private Duration duration; + + @DurationUnit(ChronoUnit.MINUTES) + private Duration customDefaultUnitDuration; + private List stringList = new ArrayList<>(); private List nestedList = new ArrayList<>(); @@ -109,10 +122,36 @@ public class AppProperties { this.dataSize = dataSize; } + public DataSize getCustomDefaultUnitDataSize() { + return this.customDefaultUnitDataSize; + } + + public void setCustomDefaultUnitDataSize(DataSize customDefaultUnitDataSize) { + this.customDefaultUnitDataSize = customDefaultUnitDataSize; + } + + public Duration getDuration() { + return this.duration; + } + + public void setDuration(Duration duration) { + this.duration = duration; + } + + public Duration getCustomDefaultUnitDuration() { + return this.customDefaultUnitDuration; + } + + public void setCustomDefaultUnitDuration(Duration customDefaultUnitDuration) { + this.customDefaultUnitDuration = customDefaultUnitDuration; + } + @Override public String toString() { - return "AppProperties{" + "string='" + string + '\'' + ", dataSize=" + dataSize + ", stringList=" + stringList - + ", nestedList=" + nestedList + ", nested=" + nested + ", nestedNotInner=" + nestedNotInner + '}'; + return "AppProperties{" + "string='" + string + '\'' + ", dataSize=" + dataSize + ", customDefaultUnitDataSize=" + + customDefaultUnitDataSize + ", duration=" + duration + ", customDefaultUnitDuration=" + + customDefaultUnitDuration + ", stringList=" + stringList + ", nestedList=" + nestedList + ", nested=" + + nested + ", nestedNotInner=" + nestedNotInner + '}'; } public static class Nested { diff --git a/boot/configuration-properties/src/main/java/com/example/configprops/records/AppPropertiesRecord.java b/boot/configuration-properties/src/main/java/com/example/configprops/records/AppPropertiesRecord.java index 541d6826..3be6df00 100644 --- a/boot/configuration-properties/src/main/java/com/example/configprops/records/AppPropertiesRecord.java +++ b/boot/configuration-properties/src/main/java/com/example/configprops/records/AppPropertiesRecord.java @@ -1,5 +1,5 @@ /* - * Copyright 2022-2024 the original author or authors. + * Copyright 2022-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,15 +16,22 @@ package com.example.configprops.records; +import java.time.Duration; +import java.time.temporal.ChronoUnit; import java.util.List; +import org.springframework.boot.convert.DataSizeUnit; +import org.springframework.boot.convert.DurationUnit; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.NestedConfigurationProperty; import org.springframework.util.unit.DataSize; +import org.springframework.util.unit.DataUnit; @ConfigurationProperties(prefix = "app.record") -public record AppPropertiesRecord(String string, DataSize dataSize, List stringList, List nestedList, - Nested nested, @NestedConfigurationProperty NestedNotInner nestedNotInner) { +public record AppPropertiesRecord(String string, DataSize dataSize, + @DataSizeUnit(DataUnit.MEGABYTES) DataSize customDefaultUnitDataSize, Duration duration, + @DurationUnit(ChronoUnit.MINUTES) Duration customDefaultUnitDuration, List stringList, + List nestedList, Nested nested, @NestedConfigurationProperty NestedNotInner nestedNotInner) { public record Nested(int aInt) { } } diff --git a/boot/configuration-properties/src/main/resources/application.yaml b/boot/configuration-properties/src/main/resources/application.yaml index b12f57bb..11c32c4a 100644 --- a/boot/configuration-properties/src/main/resources/application.yaml +++ b/boot/configuration-properties/src/main/resources/application.yaml @@ -1,6 +1,9 @@ app: string: "a-string" data-size: "1MB" + custom-default-unit-data-size: 5 + duration: "30s" + custom-default-unit-duration: 10 string-list: [ "string-1", "string-2" ] nested-list: - a-int: 1 @@ -21,6 +24,9 @@ app: app.ctor: string: "a-string" data-size: "1MB" + custom-default-unit-data-size: 5 + duration: "30s" + custom-default-unit-duration: 10 string-list: [ "string-1", "string-2" ] nested-list: - a-int: 1 @@ -33,6 +39,9 @@ app.ctor: app.record: string: "a-string" data-size: "1MB" + custom-default-unit-data-size: 5 + duration: "30s" + custom-default-unit-duration: 10 string-list: [ "string-1", "string-2" ] nested-list: - a-int: 1