diff --git a/spring-test/src/main/java/org/springframework/test/context/support/TestPropertySourceUtils.java b/spring-test/src/main/java/org/springframework/test/context/support/TestPropertySourceUtils.java index 442946450c4..913715b9513 100644 --- a/spring-test/src/main/java/org/springframework/test/context/support/TestPropertySourceUtils.java +++ b/spring-test/src/main/java/org/springframework/test/context/support/TestPropertySourceUtils.java @@ -114,7 +114,7 @@ public abstract class TestPropertySourceUtils { logger.trace(String.format("Processing locations for TestPropertySource attributes %s", attrs)); } String[] locationsArray = TestContextResourceUtils.convertToClasspathResourcePaths( - attrs.getDeclaringClass(), attrs.getLocations()); + attrs.getDeclaringClass(), true, attrs.getLocations()); locations.addAll(0, Arrays.asList(locationsArray)); if (!attrs.isInheritLocations()) { break; diff --git a/spring-test/src/main/java/org/springframework/test/context/util/TestContextResourceUtils.java b/spring-test/src/main/java/org/springframework/test/context/util/TestContextResourceUtils.java index 7258bb2de6f..645594d2b73 100644 --- a/spring-test/src/main/java/org/springframework/test/context/util/TestContextResourceUtils.java +++ b/spring-test/src/main/java/org/springframework/test/context/util/TestContextResourceUtils.java @@ -18,6 +18,7 @@ package org.springframework.test.context.util; import java.util.Arrays; import java.util.List; +import java.util.regex.Pattern; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -46,6 +47,22 @@ public abstract class TestContextResourceUtils { private static final String SLASH = "/"; + private static final Pattern PLACEHOLDER_PATTERN = Pattern.compile(".*\\$\\{[^\\}]+\\}.*"); + + + /** + * Convert the supplied paths to classpath resource paths. + * + *
Delegates to {@link #convertToClasspathResourcePaths(Class, boolean, String...)} + * with {@code false} supplied for the {@code preservePlaceholders} flag. + * @param clazz the class with which the paths are associated + * @param paths the paths to be converted + * @return a new array of converted resource paths + * @see #convertToResources + */ + public static String[] convertToClasspathResourcePaths(Class> clazz, String... paths) { + return convertToClasspathResourcePaths(clazz, false, paths); + } /** * Convert the supplied paths to classpath resource paths. @@ -63,18 +80,23 @@ public abstract class TestContextResourceUtils { * {@code classpath:}, {@code file:}, {@code http:}, etc.) will not have its * protocol modified. * - *
Each path will then be {@linkplain StringUtils#cleanPath cleaned}. + *
Each path will then be {@linkplain StringUtils#cleanPath cleaned},
+ * unless the {@code preservePlaceholders} flag is {@code true} and the path
+ * contains one or more placeholders in the form ${placeholder.name}.
* @param clazz the class with which the paths are associated
+ * @param preservePlaceholders {@code true} if placeholders should be preserved
* @param paths the paths to be converted
* @return a new array of converted resource paths
+ * @since 5.2
* @see #convertToResources
* @see ResourceUtils#CLASSPATH_URL_PREFIX
* @see ResourceUtils#FILE_URL_PREFIX
*/
- public static String[] convertToClasspathResourcePaths(Class> clazz, String... paths) {
+ public static String[] convertToClasspathResourcePaths(Class> clazz, boolean preservePlaceholders, String... paths) {
String[] convertedPaths = new String[paths.length];
for (int i = 0; i < paths.length; i++) {
String path = paths[i];
+
// Absolute path
if (path.startsWith(SLASH)) {
convertedPaths[i] = ResourceUtils.CLASSPATH_URL_PREFIX + path;
@@ -88,7 +110,10 @@ public abstract class TestContextResourceUtils {
else {
convertedPaths[i] = path;
}
- convertedPaths[i] = StringUtils.cleanPath(convertedPaths[i]);
+
+ if (!(preservePlaceholders && PLACEHOLDER_PATTERN.matcher(convertedPaths[i]).matches())) {
+ convertedPaths[i] = StringUtils.cleanPath(convertedPaths[i]);
+ }
}
return convertedPaths;
}
diff --git a/spring-test/src/test/java/org/springframework/test/context/env/ExplicitPropertiesFileTestPropertySourceTests.java b/spring-test/src/test/java/org/springframework/test/context/env/ExplicitPropertiesFileTestPropertySourceTests.java
index f399193aa45..b142718f431 100644
--- a/spring-test/src/test/java/org/springframework/test/context/env/ExplicitPropertiesFileTestPropertySourceTests.java
+++ b/spring-test/src/test/java/org/springframework/test/context/env/ExplicitPropertiesFileTestPropertySourceTests.java
@@ -18,7 +18,6 @@ package org.springframework.test.context.env;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
-import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested;
@@ -135,9 +134,8 @@ class ExplicitPropertiesFileTestPropertySourceTests {
}
@Nested
- @TestPropertySource("file:${user.dir}/../spring-test/src/test/resources/org/springframework/test/context/env/explicit.properties")
- @Disabled("Currently not supported (see https://github.com/spring-projects/spring-framework/issues/23544)")
@DisplayName("with placeholders followed immediately by relative paths")
+ @TestPropertySource("file:${user.dir}/../spring-test/src/test/resources/${current.test.package}/../env/explicit.properties")
class PlaceholdersFollowedByRelativePathsTests extends AbstractExplicitPropertiesFileTests {
}