@@ -176,6 +176,72 @@ <E> void otherConfigGroupKeyConfigured(ConfigGroupMapMapping<E> mapping, ConfigG
176176 }
177177 }
178178
179+ @ ParameterizedTest
180+ @ MethodSource ("mapMappingsAndConfigGroupKeys" )
181+ <E > void unnamedKeyConfiguredWithSameValueAsDefault (ConfigGroupMapMapping <E > mapping , ConfigGroupKey configGroupKey ) {
182+ assumeTrue (mapping .hasWithUnnamedKey (), "Only applicable to mappings with @WithUnnamedKey" );
183+ assumeTrue (mapping .hasConfigProperty1Default (), "Only applicable to mappings with @WithDefault on configProperty1" );
184+ assumeTrue (configGroupKey == ConfigGroupKey .UNNAMED , "Only applicable to the unnamed key" );
185+
186+ // Explicitly set the unnamed key's configProperty1 to the same value as the @WithDefault.
187+ // Even though the value matches the default, it comes from a real config source,
188+ // so the unnamed key should appear in the map.
189+ String configProperty1Key = mapping .configProperty1Key (configGroupKey );
190+ SmallRyeConfig config = mapping .buildConfig (configProperty1Key , "default-val" );
191+ Map <String , E > map = mapping .getConfigGroupMap (config );
192+
193+ assertTrue (map .containsKey (configGroupKey .key ),
194+ "containsKey should be true when the unnamed key is explicitly configured, even with the same value as @WithDefault" );
195+ }
196+
197+ // -- Case 2: leaf properties resolved, all from defaults → unnamed key excluded --
198+
199+ @ ConfigMapping (prefix = "case2" )
200+ interface Case2Config {
201+ @ WithDefaults
202+ @ WithUnnamedKey ("<default>" )
203+ Map <String , ConfigGroup > map ();
204+ }
205+
206+ @ Test
207+ void leafPropertiesResolvedAllFromDefaults () {
208+ SmallRyeConfig config = new SmallRyeConfigBuilder ()
209+ .withMapping (Case2Config .class )
210+ .build ();
211+
212+ Map <String , ConfigGroup > map = config .getConfigMapping (Case2Config .class ).map ();
213+
214+ assertFalse (map .containsKey ("<default>" ),
215+ "unnamed key should not appear when all leaf properties resolve from defaults only" );
216+
217+ ConfigGroup group = map .get ("<default>" );
218+ assertNotNull (group , "@WithDefaults should still provide a default via get()" );
219+ assertEquals ("default-val" , group .configProperty1 ());
220+ assertEquals (Optional .empty (), group .configProperty2 ());
221+ }
222+
223+ // -- Case 3: no leaf properties resolved (nested map) → unnamed key included via equals() fallback --
224+
225+ @ ConfigMapping (prefix = "case3" )
226+ interface Case3Config {
227+ @ WithUnnamedKey ("<default>" )
228+ Map <String , Map <String , String >> map ();
229+ }
230+
231+ @ Test
232+ void nestedMapNoLeafResolution () {
233+ SmallRyeConfig config = new SmallRyeConfigBuilder ()
234+ .withMapping (Case3Config .class )
235+ .withSources (config (
236+ "case3.map.nested-key" , "value" ))
237+ .build ();
238+
239+ Map <String , Map <String , String >> map = config .getConfigMapping (Case3Config .class ).map ();
240+
241+ assertTrue (map .containsKey ("<default>" ),
242+ "unnamed key should appear for nested maps when config is provided at the unnamed path" );
243+ }
244+
179245 // ============================
180246 // Infrastructure
181247 // ============================
@@ -200,6 +266,16 @@ static abstract class ConfigGroupMapMapping<E> {
200266
201267 abstract Map <String , E > getConfigGroupMap (SmallRyeConfig config );
202268
269+ abstract String namedKeyConfigProperty1Key ();
270+
271+ abstract String unnamedKeyConfigProperty1Key ();
272+
273+ String configProperty1Key (ConfigGroupKey configGroupKey ) {
274+ return configGroupKey == ConfigGroupKey .NAMED
275+ ? namedKeyConfigProperty1Key ()
276+ : unnamedKeyConfigProperty1Key ();
277+ }
278+
203279 abstract String namedKeyConfigProperty2Key ();
204280
205281 abstract String unnamedKeyConfigProperty2Key ();
@@ -315,6 +391,16 @@ Class<?>[] mappingClasses() {
315391 return new Class <?>[] { Config .class };
316392 }
317393
394+ @ Override
395+ String namedKeyConfigProperty1Key () {
396+ return "plain-map.map.mykey.config-property1" ;
397+ }
398+
399+ @ Override
400+ String unnamedKeyConfigProperty1Key () {
401+ return null ;
402+ }
403+
318404 @ Override
319405 String namedKeyConfigProperty2Key () {
320406 return "plain-map.map.mykey.config-property2" ;
@@ -358,6 +444,16 @@ Class<?>[] mappingClasses() {
358444 return new Class <?>[] { Config .class };
359445 }
360446
447+ @ Override
448+ String namedKeyConfigProperty1Key () {
449+ return "with-defaults-only.map.mykey.config-property1" ;
450+ }
451+
452+ @ Override
453+ String unnamedKeyConfigProperty1Key () {
454+ return null ;
455+ }
456+
361457 @ Override
362458 String namedKeyConfigProperty2Key () {
363459 return "with-defaults-only.map.mykey.config-property2" ;
@@ -401,6 +497,16 @@ Class<?>[] mappingClasses() {
401497 return new Class <?>[] { Config .class };
402498 }
403499
500+ @ Override
501+ String namedKeyConfigProperty1Key () {
502+ return "with-unnamed-key-only.map.mykey.config-property1" ;
503+ }
504+
505+ @ Override
506+ String unnamedKeyConfigProperty1Key () {
507+ return "with-unnamed-key-only.map.config-property1" ;
508+ }
509+
404510 @ Override
405511 String namedKeyConfigProperty2Key () {
406512 return "with-unnamed-key-only.map.mykey.config-property2" ;
@@ -445,6 +551,16 @@ Class<?>[] mappingClasses() {
445551 return new Class <?>[] { Config .class };
446552 }
447553
554+ @ Override
555+ String namedKeyConfigProperty1Key () {
556+ return "with-defaults-and-unnamed-key.map.mykey.config-property1" ;
557+ }
558+
559+ @ Override
560+ String unnamedKeyConfigProperty1Key () {
561+ return "with-defaults-and-unnamed-key.map.config-property1" ;
562+ }
563+
448564 @ Override
449565 String namedKeyConfigProperty2Key () {
450566 return "with-defaults-and-unnamed-key.map.mykey.config-property2" ;
@@ -490,6 +606,16 @@ Class<?>[] mappingClasses() {
490606 return new Class <?>[] { Config .class };
491607 }
492608
609+ @ Override
610+ String namedKeyConfigProperty1Key () {
611+ return "with-parent-name-defaults-and-unnamed-key.mykey.config-property1" ;
612+ }
613+
614+ @ Override
615+ String unnamedKeyConfigProperty1Key () {
616+ return "with-parent-name-defaults-and-unnamed-key.config-property1" ;
617+ }
618+
493619 @ Override
494620 String namedKeyConfigProperty2Key () {
495621 return "with-parent-name-defaults-and-unnamed-key.mykey.config-property2" ;
@@ -533,6 +659,16 @@ Class<?>[] mappingClasses() {
533659 return new Class <?>[] { Config .class };
534660 }
535661
662+ @ Override
663+ String namedKeyConfigProperty1Key () {
664+ return "with-unnamed-key-no-property-defaults.map.mykey.config-property1" ;
665+ }
666+
667+ @ Override
668+ String unnamedKeyConfigProperty1Key () {
669+ return "with-unnamed-key-no-property-defaults.map.config-property1" ;
670+ }
671+
536672 @ Override
537673 String namedKeyConfigProperty2Key () {
538674 return "with-unnamed-key-no-property-defaults.map.mykey.config-property2" ;
0 commit comments