|  | 
| 24 | 24 | import org.junit.jupiter.params.ParameterizedTest; | 
| 25 | 25 | import org.junit.jupiter.params.provider.Arguments; | 
| 26 | 26 | import org.junit.jupiter.params.provider.MethodSource; | 
|  | 27 | +import org.mockito.InOrder; | 
| 27 | 28 | 
 | 
| 28 | 29 | import org.springframework.util.PlaceholderParser.ParsedValue; | 
| 29 | 30 | import org.springframework.util.PlaceholderParser.TextPart; | 
|  | 
| 33 | 34 | import static org.assertj.core.api.Assertions.assertThatExceptionOfType; | 
| 34 | 35 | import static org.assertj.core.api.Assertions.assertThatThrownBy; | 
| 35 | 36 | import static org.mockito.BDDMockito.given; | 
|  | 37 | +import static org.mockito.Mockito.inOrder; | 
| 36 | 38 | import static org.mockito.Mockito.mock; | 
| 37 | 39 | import static org.mockito.Mockito.verify; | 
| 38 | 40 | import static org.mockito.Mockito.verifyNoMoreInteractions; | 
| @@ -220,20 +222,45 @@ static Stream<Arguments> nestedPlaceholders() { | 
| 220 | 222 | 			); | 
| 221 | 223 | 		} | 
| 222 | 224 | 
 | 
|  | 225 | +		@ParameterizedTest(name = "{0} -> {1}") | 
|  | 226 | +		@MethodSource("exactMatchPlaceholders") | 
|  | 227 | +		void placeholdersWithExactMatchAreConsidered(String text, String expected) { | 
|  | 228 | +			Properties properties = new Properties(); | 
|  | 229 | +			properties.setProperty("prefix://my-service", "example-service"); | 
|  | 230 | +			properties.setProperty("px", "prefix"); | 
|  | 231 | +			properties.setProperty("p1", "${prefix://my-service}"); | 
|  | 232 | +			assertThat(this.parser.replacePlaceholders(text, properties::getProperty)).isEqualTo(expected); | 
|  | 233 | +		} | 
|  | 234 | + | 
|  | 235 | +		static Stream<Arguments> exactMatchPlaceholders() { | 
|  | 236 | +			return Stream.of( | 
|  | 237 | +					Arguments.of("${prefix://my-service}", "example-service"), | 
|  | 238 | +					Arguments.of("${p1}", "example-service") | 
|  | 239 | +			); | 
|  | 240 | +		} | 
|  | 241 | + | 
|  | 242 | +		@Test | 
|  | 243 | +		void parseWithKeyEqualsToText() { | 
|  | 244 | +			PlaceholderResolver resolver = mockPlaceholderResolver("firstName", "Steve"); | 
|  | 245 | +			assertThat(this.parser.replacePlaceholders("${firstName}", resolver)) | 
|  | 246 | +					.isEqualTo("Steve"); | 
|  | 247 | +			verifyPlaceholderResolutions(resolver, "firstName"); | 
|  | 248 | +		} | 
|  | 249 | + | 
| 223 | 250 | 		@Test | 
| 224 | 251 | 		void parseWithHardcodedFallback() { | 
| 225 | 252 | 			PlaceholderResolver resolver = mockPlaceholderResolver(); | 
| 226 | 253 | 			assertThat(this.parser.replacePlaceholders("${firstName:Steve}", resolver)) | 
| 227 | 254 | 					.isEqualTo("Steve"); | 
| 228 |  | -			verifyPlaceholderResolutions(resolver, "firstName"); | 
|  | 255 | +			verifyPlaceholderResolutions(resolver, "firstName:Steve", "firstName"); | 
| 229 | 256 | 		} | 
| 230 | 257 | 
 | 
| 231 | 258 | 		@Test | 
| 232 | 259 | 		void parseWithNestedPlaceholderInKeyUsingFallback() { | 
| 233 | 260 | 			PlaceholderResolver resolver = mockPlaceholderResolver("firstName", "John"); | 
| 234 | 261 | 			assertThat(this.parser.replacePlaceholders("${first${invalid:Name}}", resolver)) | 
| 235 | 262 | 					.isEqualTo("John"); | 
| 236 |  | -			verifyPlaceholderResolutions(resolver, "invalid", "firstName"); | 
|  | 263 | +			verifyPlaceholderResolutions(resolver, "invalid:Name", "invalid", "firstName"); | 
| 237 | 264 | 		} | 
| 238 | 265 | 
 | 
| 239 | 266 | 		@Test | 
| @@ -348,8 +375,9 @@ PlaceholderResolver mockPlaceholderResolver(String... pairs) { | 
| 348 | 375 | 	} | 
| 349 | 376 | 
 | 
| 350 | 377 | 	void verifyPlaceholderResolutions(PlaceholderResolver mock, String... placeholders) { | 
|  | 378 | +		InOrder ordered = inOrder(mock); | 
| 351 | 379 | 		for (String placeholder : placeholders) { | 
| 352 |  | -			verify(mock).resolvePlaceholder(placeholder); | 
|  | 380 | +			ordered.verify(mock).resolvePlaceholder(placeholder); | 
| 353 | 381 | 		} | 
| 354 | 382 | 		verifyNoMoreInteractions(mock); | 
| 355 | 383 | 	} | 
|  | 
0 commit comments