2020
2121import org .junit .jupiter .api .Test ;
2222
23+ import org .springframework .boot .context .properties .source .ConfigurationPropertySources ;
2324import org .springframework .boot .context .properties .source .InvalidConfigurationPropertyValueException ;
2425import org .springframework .boot .diagnostics .FailureAnalysis ;
2526import org .springframework .boot .origin .Origin ;
2627import org .springframework .boot .origin .OriginLookup ;
2728import org .springframework .core .env .EnumerablePropertySource ;
2829import org .springframework .core .env .MapPropertySource ;
30+ import org .springframework .core .env .SystemEnvironmentPropertySource ;
2931import org .springframework .mock .env .MockEnvironment ;
32+ import org .springframework .util .ObjectUtils ;
3033
3134import static org .assertj .core .api .Assertions .assertThat ;
3235
@@ -63,6 +66,26 @@ void analysisWithKnownProperty() {
6366 .doesNotContain ("Additionally, this property is also set" );
6467 }
6568
69+ @ Test
70+ void analysisWithKnownPropertyFromSystemEnvironment () {
71+ MapPropertySource source = new SystemEnvironmentPropertySource ("systemEnvironment" ,
72+ Collections .singletonMap ("COM_EXAMPLE_TESTPROPERTY" , "invalid" ));
73+ this .environment .getPropertySources ().addFirst (source );
74+ ConfigurationPropertySources .attach (this .environment );
75+ assertThat (this .environment .getProperty ("com.example.test-property" )).isEqualTo ("invalid" );
76+ InvalidConfigurationPropertyValueException failure = new InvalidConfigurationPropertyValueException (
77+ "com.example.test-property" , "invalid" , "This is not valid." );
78+ FailureAnalysis analysis = performAnalysis (failure );
79+ assertThat (analysis .getDescription ()).contains ("com.example.test-property" )
80+ .contains ("invalid" )
81+ .contains ("property source \" systemEnvironment\" " );
82+ assertThat (analysis .getCause ()).isSameAs (failure );
83+ assertThat (analysis .getAction ()).contains ("Review the value of the property with the provided reason." );
84+ assertThat (analysis .getDescription ()).contains ("Validation failed for the following reason" )
85+ .contains ("This is not valid." )
86+ .doesNotContain ("Additionally, this property is also set" );
87+ }
88+
6689 @ Test
6790 void analysisWithKnownPropertyAndNoReason () {
6891 MapPropertySource source = new MapPropertySource ("test" , Collections .singletonMap ("test.property" , "invalid" ));
@@ -84,6 +107,8 @@ void analysisWithKnownPropertyAndOtherCandidates() {
84107 this .environment .getPropertySources ().addFirst (OriginCapablePropertySource .get (source ));
85108 this .environment .getPropertySources ().addLast (additional );
86109 this .environment .getPropertySources ().addLast (OriginCapablePropertySource .get (another ));
110+ this .environment .getPropertySources ().addLast (OriginCapablePropertySource .get ("another-again" , another ));
111+ ConfigurationPropertySources .attach (this .environment );
87112 InvalidConfigurationPropertyValueException failure = new InvalidConfigurationPropertyValueException (
88113 "test.property" , "invalid" , "This is not valid." );
89114 FailureAnalysis analysis = performAnalysis (failure );
@@ -92,7 +117,8 @@ void analysisWithKnownPropertyAndOtherCandidates() {
92117 assertThat (analysis .getDescription ())
93118 .contains ("Additionally, this property is also set in the following property sources:" )
94119 .contains ("In 'additional' with the value 'valid'" )
95- .contains ("In 'another' with the value 'test' (originating from 'TestOrigin test.property')" );
120+ .contains ("In 'another' with the value 'test' (originating from 'TestOrigin test.property')" )
121+ .doesNotContain ("another-again" );
96122 }
97123
98124 @ Test
@@ -122,7 +148,11 @@ static class OriginCapablePropertySource<T> extends EnumerablePropertySource<T>
122148 private final EnumerablePropertySource <T > propertySource ;
123149
124150 OriginCapablePropertySource (EnumerablePropertySource <T > propertySource ) {
125- super (propertySource .getName (), propertySource .getSource ());
151+ this (propertySource .getName (), propertySource );
152+ }
153+
154+ OriginCapablePropertySource (String name , EnumerablePropertySource <T > propertySource ) {
155+ super (name , propertySource .getSource ());
126156 this .propertySource = propertySource ;
127157 }
128158
@@ -138,20 +168,53 @@ public String[] getPropertyNames() {
138168
139169 @ Override
140170 public Origin getOrigin (String name ) {
141- return new Origin () {
142-
143- @ Override
144- public String toString () {
145- return "TestOrigin " + name ;
146- }
147-
148- };
171+ return new TestOrigin (name , this .propertySource .getName ());
149172 }
150173
151174 static <T > OriginCapablePropertySource <T > get (EnumerablePropertySource <T > propertySource ) {
152175 return new OriginCapablePropertySource <>(propertySource );
153176 }
154177
178+ static <T > OriginCapablePropertySource <T > get (String name , EnumerablePropertySource <T > propertySource ) {
179+ return new OriginCapablePropertySource <>(name , propertySource );
180+ }
181+
182+ static final class TestOrigin implements Origin {
183+
184+ private final String name ;
185+
186+ private final String sourceName ;
187+
188+ private TestOrigin (String name , String sourceName ) {
189+ this .name = name ;
190+ this .sourceName = sourceName ;
191+ }
192+
193+ @ Override
194+ public boolean equals (Object obj ) {
195+ if (this == obj ) {
196+ return true ;
197+ }
198+ if (obj == null || getClass () != obj .getClass ()) {
199+ return false ;
200+ }
201+ TestOrigin other = (TestOrigin ) obj ;
202+ return ObjectUtils .nullSafeEquals (this .name , other .name )
203+ && ObjectUtils .nullSafeEquals (this .sourceName , other .sourceName );
204+ }
205+
206+ @ Override
207+ public int hashCode () {
208+ return ObjectUtils .nullSafeHashCode (this .name );
209+ }
210+
211+ @ Override
212+ public String toString () {
213+ return "TestOrigin " + this .name ;
214+ }
215+
216+ }
217+
155218 }
156219
157220}
0 commit comments