@@ -373,12 +373,11 @@ public static void addInlinedPropertiesToEnvironment(ConfigurableEnvironment env
373
373
* <p>Parsing of the key-value pairs is achieved by converting all supplied
374
374
* strings into <em>virtual</em> properties files in memory and delegating to
375
375
* {@link Properties#load(java.io.Reader)} to parse each virtual file.
376
- * <p>Generally speaking, the ordering of property names will be preserved in
377
- * the returned map, analogous to the order in which the key-value pairs are
378
- * supplied to this method. However, if a single string contains multiple
379
- * key-value pairs separated by newlines — for example, when supplied by
380
- * a user via a <em>text block</em> — the ordering of property names for
381
- * those particular key-value pairs cannot be guaranteed in the returned map.
376
+ * <p>The ordering of property names will be preserved in the returned map,
377
+ * analogous to the order in which the key-value pairs are supplied to this
378
+ * method. This also applies if a single string contains multiple key-value
379
+ * pairs separated by newlines — for example, when supplied by a user
380
+ * via a <em>text block</em>.
382
381
* <p>For a full discussion of <em>inlined properties</em>, consult the Javadoc
383
382
* for {@link TestPropertySource#properties}.
384
383
* @param inlinedProperties the inlined properties to convert; potentially empty
@@ -390,26 +389,21 @@ public static void addInlinedPropertiesToEnvironment(ConfigurableEnvironment env
390
389
*/
391
390
public static Map <String , Object > convertInlinedPropertiesToMap (String ... inlinedProperties ) {
392
391
Assert .notNull (inlinedProperties , "'inlinedProperties' must not be null" );
393
- Map <String , Object > map = new LinkedHashMap <>();
394
- Properties props = new Properties ();
392
+ SequencedProperties sequencedProperties = new SequencedProperties ();
395
393
396
- for (String pair : inlinedProperties ) {
397
- if (!StringUtils .hasText (pair )) {
394
+ for (String input : inlinedProperties ) {
395
+ if (!StringUtils .hasText (input )) {
398
396
continue ;
399
397
}
400
398
try {
401
- props .load (new StringReader (pair ));
399
+ sequencedProperties .load (new StringReader (input ));
402
400
}
403
401
catch (Exception ex ) {
404
- throw new IllegalStateException ("Failed to load test environment properties from [" + pair + "]" , ex );
402
+ throw new IllegalStateException ("Failed to load test environment properties from [" + input + "]" , ex );
405
403
}
406
- for (String name : props .stringPropertyNames ()) {
407
- map .put (name , props .getProperty (name ));
408
- }
409
- props .clear ();
410
404
}
411
405
412
- return map ;
406
+ return sequencedProperties . map ;
413
407
}
414
408
415
409
private static <T extends Annotation > List <List <MergedAnnotation <T >>> findRepeatableAnnotations (
@@ -456,4 +450,24 @@ private static <A extends Annotation> Comparator<MergedAnnotation<A>> highMetaDi
456
450
return Comparator .<MergedAnnotation <A >> comparingInt (MergedAnnotation ::getDistance ).reversed ();
457
451
}
458
452
453
+ /**
454
+ * Extension of {@link Properties} that mimics a {@code SequencedMap} by
455
+ * tracking all added properties in a {@link LinkedHashMap} that can be
456
+ * accessed directly via the {@code map} field.
457
+ * @since 6.1
458
+ */
459
+ @ SuppressWarnings ("serial" )
460
+ private static class SequencedProperties extends Properties {
461
+
462
+ final Map <String , Object > map = new LinkedHashMap <>();
463
+
464
+ @ Override
465
+ public synchronized Object put (Object key , Object value ) {
466
+ if (key instanceof String str ) {
467
+ this .map .put (str , value );
468
+ }
469
+ return super .put (key , value );
470
+ }
471
+ }
472
+
459
473
}
0 commit comments