Support custom properties file formats in @TestPropertySource
Spring Framework 4.3 introduced the `PropertySourceFactory` SPI for use with `@PropertySource` on `@Configuration` classes; however, prior to this commit there was no mechanism to support custom properties file formats in `@TestPropertySource` for integration tests. This commit introduces support for configuring a custom `PropertySourceFactory` via a new `factory` attribute in `@TestPropertySource` in order to support custom file formats such as JSON, YAML, etc. For example, if you create a YamlPropertySourceFactory, you can use it in integration tests as follows. @SpringJUnitConfig @TestPropertySource(locations = "/test.yaml", factory = YamlPropertySourceFactory.class) class MyTestClass { /* ... /* } If a custom factory is not specified, traditional `*.properties` and `*.xml` based `java.util.Properties` file formats are supported, which was the existing behavior. Closes gh-30981
This commit is contained in:
parent
b80872b762
commit
04cce0bafd
|
@ -16,7 +16,7 @@ SPI, but `@TestPropertySource` is not supported with implementations of the olde
|
|||
`ContextLoader` SPI.
|
||||
|
||||
Implementations of `SmartContextLoader` gain access to merged test property source values
|
||||
through the `getPropertySourceLocations()` and `getPropertySourceProperties()` methods in
|
||||
through the `getPropertySourceDescriptors()` and `getPropertySourceProperties()` methods in
|
||||
`MergedContextConfiguration`.
|
||||
====
|
||||
|
||||
|
@ -26,8 +26,11 @@ through the `getPropertySourceLocations()` and `getPropertySourceProperties()` m
|
|||
You can configure test properties files by using the `locations` or `value` attribute of
|
||||
`@TestPropertySource`.
|
||||
|
||||
Both traditional and XML-based properties file formats are supported -- for example,
|
||||
`"classpath:/com/example/test.properties"` or `"file:///path/to/file.xml"`.
|
||||
By default, both traditional and XML-based `java.util.Properties` file formats are
|
||||
supported -- for example, `"classpath:/com/example/test.properties"` or
|
||||
`"file:///path/to/file.xml"`. As of Spring Framework 6.1, you can configure a custom
|
||||
`PropertySourceFactory` via the `factory` attribute in `@TestPropertySource` in order to
|
||||
support a different file format such as JSON, YAML, etc.
|
||||
|
||||
Each path is interpreted as a Spring `Resource`. A plain path (for example,
|
||||
`"test.properties"`) is treated as a classpath resource that is relative to the package
|
||||
|
@ -35,8 +38,8 @@ in which the test class is defined. A path starting with a slash is treated as a
|
|||
absolute classpath resource (for example: `"/org/example/test.xml"`). A path that
|
||||
references a URL (for example, a path prefixed with `classpath:`, `file:`, or `http:`) is
|
||||
loaded by using the specified resource protocol. Resource location wildcards (such as
|
||||
`**/*.properties`) are not permitted: Each location must evaluate to exactly one
|
||||
`.properties` or `.xml` resource.
|
||||
`{asterisk}{asterisk}/{asterisk}.properties`) are not permitted: Each location must
|
||||
evaluate to exactly one properties resource.
|
||||
|
||||
The following example uses a test properties file:
|
||||
|
||||
|
|
|
@ -85,6 +85,7 @@ dependencies {
|
|||
testRuntimeOnly("org.junit.vintage:junit-vintage-engine") {
|
||||
exclude group: "junit", module: "junit"
|
||||
}
|
||||
testRuntimeOnly("org.yaml:snakeyaml")
|
||||
}
|
||||
|
||||
// Prevent xml-apis from being used so that the corresponding XML APIs from
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -20,10 +20,12 @@ import java.io.Serializable;
|
|||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextInitializer;
|
||||
import org.springframework.core.io.support.PropertySourceDescriptor;
|
||||
import org.springframework.core.style.DefaultToStringStyler;
|
||||
import org.springframework.core.style.SimpleValueStyler;
|
||||
import org.springframework.core.style.ToStringCreator;
|
||||
|
@ -91,6 +93,8 @@ public class MergedContextConfiguration implements Serializable {
|
|||
|
||||
private final String[] activeProfiles;
|
||||
|
||||
private final List<PropertySourceDescriptor> propertySourceDescriptors;
|
||||
|
||||
private final String[] propertySourceLocations;
|
||||
|
||||
private final String[] propertySourceProperties;
|
||||
|
@ -151,7 +155,7 @@ public class MergedContextConfiguration implements Serializable {
|
|||
* @param activeProfiles the merged active bean definition profiles
|
||||
* @param contextLoader the resolved {@code ContextLoader}
|
||||
* @param cacheAwareContextLoaderDelegate a cache-aware context loader
|
||||
* delegate with which to retrieve the parent context
|
||||
* delegate with which to retrieve the parent {@code ApplicationContext}
|
||||
* @param parent the parent configuration or {@code null} if there is no parent
|
||||
* @since 3.2.2
|
||||
*/
|
||||
|
@ -172,9 +176,10 @@ public class MergedContextConfiguration implements Serializable {
|
|||
*/
|
||||
public MergedContextConfiguration(MergedContextConfiguration mergedConfig) {
|
||||
this(mergedConfig.testClass, mergedConfig.locations, mergedConfig.classes,
|
||||
mergedConfig.contextInitializerClasses, mergedConfig.activeProfiles, mergedConfig.propertySourceLocations,
|
||||
mergedConfig.propertySourceProperties, mergedConfig.contextCustomizers,
|
||||
mergedConfig.contextLoader, mergedConfig.cacheAwareContextLoaderDelegate, mergedConfig.parent);
|
||||
mergedConfig.contextInitializerClasses, mergedConfig.activeProfiles,
|
||||
mergedConfig.propertySourceDescriptors, mergedConfig.propertySourceProperties,
|
||||
mergedConfig.contextCustomizers, mergedConfig.contextLoader,
|
||||
mergedConfig.cacheAwareContextLoaderDelegate, mergedConfig.parent);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -196,10 +201,13 @@ public class MergedContextConfiguration implements Serializable {
|
|||
* @param propertySourceProperties the merged {@code PropertySource} properties
|
||||
* @param contextLoader the resolved {@code ContextLoader}
|
||||
* @param cacheAwareContextLoaderDelegate a cache-aware context loader
|
||||
* delegate with which to retrieve the parent context
|
||||
* delegate with which to retrieve the parent {@code ApplicationContext}
|
||||
* @param parent the parent configuration or {@code null} if there is no parent
|
||||
* @since 4.1
|
||||
* @deprecated since 6.1 in favor of
|
||||
* {@link #MergedContextConfiguration(Class, String[], Class[], Set, String[], List, String[], Set, ContextLoader, CacheAwareContextLoaderDelegate, MergedContextConfiguration)}
|
||||
*/
|
||||
@Deprecated(since = "6.1")
|
||||
public MergedContextConfiguration(Class<?> testClass, @Nullable String[] locations, @Nullable Class<?>[] classes,
|
||||
@Nullable Set<Class<? extends ApplicationContextInitializer<?>>> contextInitializerClasses,
|
||||
@Nullable String[] activeProfiles, @Nullable String[] propertySourceLocations,
|
||||
|
@ -233,10 +241,13 @@ public class MergedContextConfiguration implements Serializable {
|
|||
* @param contextCustomizers the context customizers
|
||||
* @param contextLoader the resolved {@code ContextLoader}
|
||||
* @param cacheAwareContextLoaderDelegate a cache-aware context loader
|
||||
* delegate with which to retrieve the parent context
|
||||
* delegate with which to retrieve the parent {@code ApplicationContext}
|
||||
* @param parent the parent configuration or {@code null} if there is no parent
|
||||
* @since 4.3
|
||||
* @deprecated since 6.1 in favor of
|
||||
* {@link #MergedContextConfiguration(Class, String[], Class[], Set, String[], List, String[], Set, ContextLoader, CacheAwareContextLoaderDelegate, MergedContextConfiguration)}
|
||||
*/
|
||||
@Deprecated(since = "6.1")
|
||||
public MergedContextConfiguration(Class<?> testClass, @Nullable String[] locations, @Nullable Class<?>[] classes,
|
||||
@Nullable Set<Class<? extends ApplicationContextInitializer<?>>> contextInitializerClasses,
|
||||
@Nullable String[] activeProfiles, @Nullable String[] propertySourceLocations,
|
||||
|
@ -244,12 +255,52 @@ public class MergedContextConfiguration implements Serializable {
|
|||
ContextLoader contextLoader, @Nullable CacheAwareContextLoaderDelegate cacheAwareContextLoaderDelegate,
|
||||
@Nullable MergedContextConfiguration parent) {
|
||||
|
||||
this(testClass, locations, classes, contextInitializerClasses, activeProfiles,
|
||||
List.of(new PropertySourceDescriptor(processStrings(propertySourceLocations))),
|
||||
propertySourceProperties, contextCustomizers, contextLoader, cacheAwareContextLoaderDelegate,
|
||||
parent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@code MergedContextConfiguration} instance for the supplied
|
||||
* parameters.
|
||||
* <p>If a {@code null} value is supplied for {@code locations}, {@code classes},
|
||||
* {@code activeProfiles}, or {@code propertySourceProperties} an empty array
|
||||
* will be stored instead. If a {@code null} value is supplied for
|
||||
* {@code contextInitializerClasses} or {@code contextCustomizers}, an empty
|
||||
* set will be stored instead. Furthermore, active profiles will be sorted,
|
||||
* and duplicate profiles will be removed.
|
||||
* @param testClass the test class for which the configuration was merged
|
||||
* @param locations the merged context resource locations
|
||||
* @param classes the merged annotated classes
|
||||
* @param contextInitializerClasses the merged context initializer classes
|
||||
* @param activeProfiles the merged active bean definition profiles
|
||||
* @param propertySourceDescriptors the merged property source descriptors
|
||||
* @param propertySourceProperties the merged inlined properties
|
||||
* @param contextCustomizers the context customizers
|
||||
* @param contextLoader the resolved {@code ContextLoader}
|
||||
* @param cacheAwareContextLoaderDelegate a cache-aware context loader
|
||||
* delegate with which to retrieve the parent {@code ApplicationContext}
|
||||
* @param parent the parent configuration or {@code null} if there is no parent
|
||||
* @since 6.1
|
||||
*/
|
||||
public MergedContextConfiguration(Class<?> testClass, @Nullable String[] locations, @Nullable Class<?>[] classes,
|
||||
@Nullable Set<Class<? extends ApplicationContextInitializer<?>>> contextInitializerClasses,
|
||||
@Nullable String[] activeProfiles, List<PropertySourceDescriptor> propertySourceDescriptors,
|
||||
@Nullable String[] propertySourceProperties, @Nullable Set<ContextCustomizer> contextCustomizers,
|
||||
ContextLoader contextLoader, @Nullable CacheAwareContextLoaderDelegate cacheAwareContextLoaderDelegate,
|
||||
@Nullable MergedContextConfiguration parent) {
|
||||
|
||||
this.testClass = testClass;
|
||||
this.locations = processStrings(locations);
|
||||
this.classes = processClasses(classes);
|
||||
this.contextInitializerClasses = processContextInitializerClasses(contextInitializerClasses);
|
||||
this.activeProfiles = processActiveProfiles(activeProfiles);
|
||||
this.propertySourceLocations = processStrings(propertySourceLocations);
|
||||
this.propertySourceDescriptors = Collections.unmodifiableList(propertySourceDescriptors);
|
||||
this.propertySourceLocations = this.propertySourceDescriptors.stream()
|
||||
.map(PropertySourceDescriptor::locations)
|
||||
.flatMap(List::stream)
|
||||
.toArray(String[]::new);
|
||||
this.propertySourceProperties = processStrings(propertySourceProperties);
|
||||
this.contextCustomizers = processContextCustomizers(contextCustomizers);
|
||||
this.contextLoader = contextLoader;
|
||||
|
@ -338,18 +389,32 @@ public class MergedContextConfiguration implements Serializable {
|
|||
}
|
||||
|
||||
/**
|
||||
* Get the merged resource locations for test {@code PropertySources}
|
||||
* Get the merged descriptors for resource locations for test {@code PropertySources}
|
||||
* for the {@linkplain #getTestClass() test class}.
|
||||
* <p>Properties will be loaded into the {@code Environment}'s set of
|
||||
* {@code PropertySources}.
|
||||
* @since 6.1
|
||||
* @see TestPropertySource#locations
|
||||
* @see TestPropertySource#factory
|
||||
*/
|
||||
public List<PropertySourceDescriptor> getPropertySourceDescriptors() {
|
||||
return this.propertySourceDescriptors;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the merged resource locations of properties files for the
|
||||
* {@linkplain #getTestClass() test class}.
|
||||
* @see TestPropertySource#locations
|
||||
* @see java.util.Properties
|
||||
* @deprecated since 6.1 in favor of {@link #getPropertySourceDescriptors()}
|
||||
*/
|
||||
@Deprecated(since = "6.1")
|
||||
public String[] getPropertySourceLocations() {
|
||||
return this.propertySourceLocations;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the merged test {@code PropertySource} properties for the
|
||||
* {@linkplain #getTestClass() test class}.
|
||||
* Get the merged inlined properties for the {@linkplain #getTestClass() test class}.
|
||||
* <p>Properties will be loaded into the {@code Environment}'s set of
|
||||
* {@code PropertySources}.
|
||||
* @see TestPropertySource#properties
|
||||
|
@ -408,12 +473,13 @@ public class MergedContextConfiguration implements Serializable {
|
|||
|
||||
/**
|
||||
* Determine if the supplied object is equal to this {@code MergedContextConfiguration}
|
||||
* instance by comparing both object's {@linkplain #getLocations() locations},
|
||||
* instance by comparing both objects' {@linkplain #getLocations() locations},
|
||||
* {@linkplain #getClasses() annotated classes},
|
||||
* {@linkplain #getContextInitializerClasses() context initializer classes},
|
||||
* {@linkplain #getActiveProfiles() active profiles},
|
||||
* {@linkplain #getPropertySourceLocations() property source locations},
|
||||
* {@linkplain #getPropertySourceDescriptors() property source descriptors},
|
||||
* {@linkplain #getPropertySourceProperties() property source properties},
|
||||
* {@linkplain #getContextCustomizers() context customizers},
|
||||
* {@linkplain #getParent() parents}, and the fully qualified names of their
|
||||
* {@link #getContextLoader() ContextLoaders}.
|
||||
*/
|
||||
|
@ -439,7 +505,7 @@ public class MergedContextConfiguration implements Serializable {
|
|||
if (!Arrays.equals(this.activeProfiles, otherConfig.activeProfiles)) {
|
||||
return false;
|
||||
}
|
||||
if (!Arrays.equals(this.propertySourceLocations, otherConfig.propertySourceLocations)) {
|
||||
if (!this.propertySourceDescriptors.equals(otherConfig.propertySourceDescriptors)) {
|
||||
return false;
|
||||
}
|
||||
if (!Arrays.equals(this.propertySourceProperties, otherConfig.propertySourceProperties)) {
|
||||
|
@ -476,7 +542,7 @@ public class MergedContextConfiguration implements Serializable {
|
|||
result = 31 * result + Arrays.hashCode(this.classes);
|
||||
result = 31 * result + this.contextInitializerClasses.hashCode();
|
||||
result = 31 * result + Arrays.hashCode(this.activeProfiles);
|
||||
result = 31 * result + Arrays.hashCode(this.propertySourceLocations);
|
||||
result = 31 * result + this.propertySourceDescriptors.hashCode();
|
||||
result = 31 * result + Arrays.hashCode(this.propertySourceProperties);
|
||||
result = 31 * result + this.contextCustomizers.hashCode();
|
||||
result = 31 * result + (this.parent != null ? this.parent.hashCode() : 0);
|
||||
|
@ -489,7 +555,7 @@ public class MergedContextConfiguration implements Serializable {
|
|||
* {@linkplain #getLocations() locations}, {@linkplain #getClasses() annotated classes},
|
||||
* {@linkplain #getContextInitializerClasses() context initializer classes},
|
||||
* {@linkplain #getActiveProfiles() active profiles},
|
||||
* {@linkplain #getPropertySourceLocations() property source locations},
|
||||
* {@linkplain #getPropertySourceDescriptors() property source descriptors},
|
||||
* {@linkplain #getPropertySourceProperties() property source properties},
|
||||
* {@linkplain #getContextCustomizers() context customizers},
|
||||
* the name of the {@link #getContextLoader() ContextLoader}, and the
|
||||
|
@ -503,7 +569,7 @@ public class MergedContextConfiguration implements Serializable {
|
|||
.append("classes", this.classes)
|
||||
.append("contextInitializerClasses", this.contextInitializerClasses)
|
||||
.append("activeProfiles", this.activeProfiles)
|
||||
.append("propertySourceLocations", this.propertySourceLocations)
|
||||
.append("propertySourceDescriptors", this.propertySourceDescriptors)
|
||||
.append("propertySourceProperties", this.propertySourceProperties)
|
||||
.append("contextCustomizers", this.contextCustomizers)
|
||||
.append("contextLoader", (this.contextLoader != null ? this.contextLoader.getClass() : null))
|
||||
|
@ -512,7 +578,7 @@ public class MergedContextConfiguration implements Serializable {
|
|||
}
|
||||
|
||||
|
||||
private static String[] processStrings(@Nullable String[] array) {
|
||||
protected static String[] processStrings(@Nullable String[] array) {
|
||||
return (array != null ? array : EMPTY_STRING_ARRAY);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -25,6 +25,7 @@ import java.lang.annotation.RetentionPolicy;
|
|||
import java.lang.annotation.Target;
|
||||
|
||||
import org.springframework.core.annotation.AliasFor;
|
||||
import org.springframework.core.io.support.PropertySourceFactory;
|
||||
|
||||
/**
|
||||
* {@code @TestPropertySource} is a class-level annotation that is used to
|
||||
|
@ -113,9 +114,10 @@ public @interface TestPropertySource {
|
|||
* will be added to the enclosing {@code Environment} as its own property
|
||||
* source, in the order declared.
|
||||
* <h4>Supported File Formats</h4>
|
||||
* <p>Both traditional and XML-based properties file formats are supported
|
||||
* — for example, {@code "classpath:/com/example/test.properties"}
|
||||
* or {@code "file:/path/to/file.xml"}.
|
||||
* <p>By default, both traditional and XML-based properties file formats are
|
||||
* supported — for example, {@code "classpath:/com/example/test.properties"}
|
||||
* or {@code "file:/path/to/file.xml"}. To support a different file format,
|
||||
* configure an appropriate {@link #factory() PropertySourceFactory}.
|
||||
* <h4>Path Resource Semantics</h4>
|
||||
* <p>Each path will be interpreted as a Spring
|
||||
* {@link org.springframework.core.io.Resource Resource}. A plain path
|
||||
|
@ -129,9 +131,8 @@ public @interface TestPropertySource {
|
|||
* {@link org.springframework.util.ResourceUtils#FILE_URL_PREFIX file:},
|
||||
* {@code http:}, etc.) will be loaded using the specified resource protocol.
|
||||
* Resource location wildcards (e.g. <code>**/*.properties</code>)
|
||||
* are not permitted: each location must evaluate to exactly one
|
||||
* {@code .properties} or {@code .xml} resource. Property placeholders
|
||||
* in paths (i.e., <code>${...}</code>) will be
|
||||
* are not permitted: each location must evaluate to exactly one properties
|
||||
* resource. Property placeholders in paths (i.e., <code>${...}</code>) will be
|
||||
* {@linkplain org.springframework.core.env.Environment#resolveRequiredPlaceholders(String) resolved}
|
||||
* against the {@code Environment}.
|
||||
* <h4>Default Properties File Detection</h4>
|
||||
|
@ -144,6 +145,7 @@ public @interface TestPropertySource {
|
|||
* @see #inheritLocations
|
||||
* @see #value
|
||||
* @see #properties
|
||||
* @see #factory
|
||||
* @see org.springframework.core.env.PropertySource
|
||||
*/
|
||||
@AliasFor("value")
|
||||
|
@ -278,4 +280,15 @@ public @interface TestPropertySource {
|
|||
*/
|
||||
boolean inheritProperties() default true;
|
||||
|
||||
/**
|
||||
* Specify a custom {@link PropertySourceFactory}, if any.
|
||||
* <p>By default, a factory for standard resource files will be used which
|
||||
* supports {@code *.properties} and {@code *.xml} file formats for
|
||||
* {@link java.util.Properties}.
|
||||
* @since 6.1
|
||||
* @see org.springframework.core.io.support.DefaultPropertySourceFactory
|
||||
* @see org.springframework.core.io.support.ResourcePropertySource
|
||||
*/
|
||||
Class<? extends PropertySourceFactory> factory() default PropertySourceFactory.class;
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -53,6 +53,7 @@ class MergedContextConfigurationRuntimeHints {
|
|||
private static final Method getResourceBasePathMethod = loadGetResourceBasePathMethod();
|
||||
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public void registerHints(RuntimeHints runtimeHints, MergedContextConfiguration mergedConfig, ClassLoader classLoader) {
|
||||
// @ContextConfiguration(loader = ...)
|
||||
ContextLoader contextLoader = mergedConfig.getContextLoader();
|
||||
|
|
|
@ -127,15 +127,15 @@ public abstract class AbstractContextLoader implements SmartContextLoader {
|
|||
* @param context the newly created application context
|
||||
* @param mergedConfig the merged context configuration
|
||||
* @since 3.2
|
||||
* @see TestPropertySourceUtils#addPropertiesFilesToEnvironment
|
||||
* @see TestPropertySourceUtils#addInlinedPropertiesToEnvironment
|
||||
* @see TestPropertySourceUtils#addPropertySourcesToEnvironment(ConfigurableApplicationContext, List)
|
||||
* @see TestPropertySourceUtils#addInlinedPropertiesToEnvironment(ConfigurableApplicationContext, String...)
|
||||
* @see ApplicationContextInitializer#initialize(ConfigurableApplicationContext)
|
||||
* @see #loadContext(MergedContextConfiguration)
|
||||
* @see ConfigurableApplicationContext#setId
|
||||
*/
|
||||
protected void prepareContext(ConfigurableApplicationContext context, MergedContextConfiguration mergedConfig) {
|
||||
context.getEnvironment().setActiveProfiles(mergedConfig.getActiveProfiles());
|
||||
TestPropertySourceUtils.addPropertiesFilesToEnvironment(context, mergedConfig.getPropertySourceLocations());
|
||||
TestPropertySourceUtils.addPropertySourcesToEnvironment(context, mergedConfig.getPropertySourceDescriptors());
|
||||
TestPropertySourceUtils.addInlinedPropertiesToEnvironment(context, mergedConfig.getPropertySourceProperties());
|
||||
invokeApplicationContextInitializers(context, mergedConfig);
|
||||
}
|
||||
|
|
|
@ -368,7 +368,7 @@ public abstract class AbstractTestContextBootstrapper implements TestContextBoot
|
|||
StringUtils.toStringArray(locations), ClassUtils.toClassArray(classes),
|
||||
ApplicationContextInitializerUtils.resolveInitializerClasses(configAttributesList),
|
||||
ActiveProfilesUtils.resolveActiveProfiles(testClass),
|
||||
mergedTestPropertySources.getLocations(),
|
||||
mergedTestPropertySources.getPropertySourceDescriptors(),
|
||||
mergedTestPropertySources.getProperties(),
|
||||
contextCustomizers, contextLoader, cacheAwareContextLoaderDelegate, parentConfig);
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -17,7 +17,9 @@
|
|||
package org.springframework.test.context.support;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.core.io.support.PropertySourceDescriptor;
|
||||
import org.springframework.core.style.DefaultToStringStyler;
|
||||
import org.springframework.core.style.SimpleValueStyler;
|
||||
import org.springframework.core.style.ToStringCreator;
|
||||
|
@ -36,9 +38,9 @@ import org.springframework.util.Assert;
|
|||
*/
|
||||
class MergedTestPropertySources {
|
||||
|
||||
private static final MergedTestPropertySources empty = new MergedTestPropertySources(new String[0], new String[0]);
|
||||
private static final MergedTestPropertySources empty = new MergedTestPropertySources(List.of(), new String[0]);
|
||||
|
||||
private final String[] locations;
|
||||
private final List<PropertySourceDescriptor> descriptors;
|
||||
|
||||
private final String[] properties;
|
||||
|
||||
|
@ -53,25 +55,25 @@ class MergedTestPropertySources {
|
|||
|
||||
/**
|
||||
* Create a {@code MergedTestPropertySources} instance with the supplied
|
||||
* {@code locations} and {@code properties}.
|
||||
* @param locations the resource locations of properties files; may be
|
||||
* empty but never {@code null}
|
||||
* {@code descriptors} and {@code properties}.
|
||||
* @param descriptors the descriptors for resource locations
|
||||
* of properties files; may be empty but never {@code null}
|
||||
* @param properties the properties in the form of {@code key=value} pairs;
|
||||
* may be empty but never {@code null}
|
||||
*/
|
||||
MergedTestPropertySources(String[] locations, String[] properties) {
|
||||
Assert.notNull(locations, "The locations array must not be null");
|
||||
MergedTestPropertySources(List<PropertySourceDescriptor> descriptors, String[] properties) {
|
||||
Assert.notNull(descriptors, "The descriptors list must not be null");
|
||||
Assert.notNull(properties, "The properties array must not be null");
|
||||
this.locations = locations;
|
||||
this.descriptors = descriptors;
|
||||
this.properties = properties;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the resource locations of properties files.
|
||||
* Get the descriptors for resource locations of properties files.
|
||||
* @see TestPropertySource#locations()
|
||||
*/
|
||||
String[] getLocations() {
|
||||
return this.locations;
|
||||
List<PropertySourceDescriptor> getPropertySourceDescriptors() {
|
||||
return this.descriptors;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -84,8 +86,8 @@ class MergedTestPropertySources {
|
|||
|
||||
/**
|
||||
* Determine if the supplied object is equal to this {@code MergedTestPropertySources}
|
||||
* instance by comparing both object's {@linkplain #getLocations() locations}
|
||||
* and {@linkplain #getProperties() properties}.
|
||||
* instance by comparing both objects' {@linkplain #getPropertySourceDescriptors()
|
||||
* descriptors} and {@linkplain #getProperties() properties}.
|
||||
* @since 5.3
|
||||
*/
|
||||
@Override
|
||||
|
@ -98,7 +100,7 @@ class MergedTestPropertySources {
|
|||
}
|
||||
|
||||
MergedTestPropertySources that = (MergedTestPropertySources) other;
|
||||
if (!Arrays.equals(this.locations, that.locations)) {
|
||||
if (!this.descriptors.equals(that.descriptors)) {
|
||||
return false;
|
||||
}
|
||||
if (!Arrays.equals(this.properties, that.properties)) {
|
||||
|
@ -115,7 +117,7 @@ class MergedTestPropertySources {
|
|||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = Arrays.hashCode(this.locations);
|
||||
int result = this.descriptors.hashCode();
|
||||
result = 31 * result + Arrays.hashCode(this.properties);
|
||||
return result;
|
||||
}
|
||||
|
@ -128,7 +130,7 @@ class MergedTestPropertySources {
|
|||
@Override
|
||||
public String toString() {
|
||||
return new ToStringCreator(this, new DefaultToStringStyler(new SimpleValueStyler()))
|
||||
.append("locations", this.locations)
|
||||
.append("descriptors", this.descriptors)
|
||||
.append("properties", this.properties)
|
||||
.toString();
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -25,12 +25,15 @@ import org.apache.commons.logging.LogFactory;
|
|||
|
||||
import org.springframework.core.annotation.MergedAnnotation;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.core.io.support.PropertySourceDescriptor;
|
||||
import org.springframework.core.io.support.PropertySourceFactory;
|
||||
import org.springframework.core.log.LogMessage;
|
||||
import org.springframework.core.style.DefaultToStringStyler;
|
||||
import org.springframework.core.style.SimpleValueStyler;
|
||||
import org.springframework.core.style.ToStringCreator;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.test.context.TestPropertySource;
|
||||
import org.springframework.test.context.util.TestContextResourceUtils;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
@ -61,7 +64,7 @@ class TestPropertySourceAttributes {
|
|||
|
||||
private final MergedAnnotation<?> rootAnnotation;
|
||||
|
||||
private final List<String> locations = new ArrayList<>();
|
||||
private final List<PropertySourceDescriptor> descriptors = new ArrayList<>();
|
||||
|
||||
private final boolean inheritLocations;
|
||||
|
||||
|
@ -70,12 +73,13 @@ class TestPropertySourceAttributes {
|
|||
private final boolean inheritProperties;
|
||||
|
||||
|
||||
TestPropertySourceAttributes(MergedAnnotation<TestPropertySource> annotation) {
|
||||
this.declaringClass = declaringClass(annotation);
|
||||
this.rootAnnotation = annotation.getRoot();
|
||||
this.inheritLocations = annotation.getBoolean("inheritLocations");
|
||||
this.inheritProperties = annotation.getBoolean("inheritProperties");
|
||||
addPropertiesAndLocationsFrom(annotation);
|
||||
@SuppressWarnings("unchecked")
|
||||
TestPropertySourceAttributes(MergedAnnotation<TestPropertySource> mergedAnnotation) {
|
||||
this.declaringClass = declaringClass(mergedAnnotation);
|
||||
this.rootAnnotation = mergedAnnotation.getRoot();
|
||||
this.inheritLocations = mergedAnnotation.getBoolean("inheritLocations");
|
||||
this.inheritProperties = mergedAnnotation.getBoolean("inheritProperties");
|
||||
addPropertiesAndLocationsFrom(mergedAnnotation, this.declaringClass);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -112,29 +116,52 @@ class TestPropertySourceAttributes {
|
|||
attributeName));
|
||||
}
|
||||
|
||||
private void addPropertiesAndLocationsFrom(MergedAnnotation<TestPropertySource> mergedAnnotation) {
|
||||
@SuppressWarnings("unchecked")
|
||||
private void addPropertiesAndLocationsFrom(MergedAnnotation<TestPropertySource> mergedAnnotation,
|
||||
Class<?> declaringClass) {
|
||||
|
||||
String[] locations = mergedAnnotation.getStringArray("locations");
|
||||
String[] properties = mergedAnnotation.getStringArray("properties");
|
||||
addPropertiesAndLocations(locations, properties, declaringClass(mergedAnnotation), false);
|
||||
String[] convertedLocations =
|
||||
TestContextResourceUtils.convertToClasspathResourcePaths(declaringClass, true, locations);
|
||||
Class<? extends PropertySourceFactory> factoryClass =
|
||||
(Class<? extends PropertySourceFactory>) mergedAnnotation.getClass("factory");
|
||||
PropertySourceDescriptor descriptor = new PropertySourceDescriptor(
|
||||
Arrays.asList(convertedLocations), false, null, factoryClass, null);
|
||||
addPropertiesAndLocations(List.of(descriptor), properties, declaringClass, false);
|
||||
}
|
||||
|
||||
private void mergePropertiesAndLocationsFrom(TestPropertySourceAttributes attributes) {
|
||||
addPropertiesAndLocations(attributes.getLocations(), attributes.getProperties(),
|
||||
addPropertiesAndLocations(attributes.getPropertySourceDescriptors(), attributes.getProperties(),
|
||||
attributes.getDeclaringClass(), true);
|
||||
}
|
||||
|
||||
private void addPropertiesAndLocations(String[] locations, String[] properties,
|
||||
private void addPropertiesAndLocations(List<PropertySourceDescriptor> descriptors, String[] properties,
|
||||
Class<?> declaringClass, boolean prepend) {
|
||||
|
||||
if (ObjectUtils.isEmpty(locations) && ObjectUtils.isEmpty(properties)) {
|
||||
addAll(prepend, this.locations, detectDefaultPropertiesFile(declaringClass));
|
||||
if (hasNoLocations(descriptors) && ObjectUtils.isEmpty(properties)) {
|
||||
String defaultPropertiesFile = detectDefaultPropertiesFile(declaringClass);
|
||||
addAll(prepend, this.descriptors, List.of(new PropertySourceDescriptor(defaultPropertiesFile)));
|
||||
}
|
||||
else {
|
||||
addAll(prepend, this.locations, locations);
|
||||
addAll(prepend, this.descriptors, descriptors);
|
||||
addAll(prepend, this.properties, properties);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add all the supplied elements to the provided list, honoring the
|
||||
* {@code prepend} flag.
|
||||
* <p>If the {@code prepend} flag is {@code false}, the elements will be appended
|
||||
* to the list.
|
||||
* @param prepend whether the elements should be prepended to the list
|
||||
* @param list the list to which to add the elements
|
||||
* @param elements the elements to add to the list
|
||||
*/
|
||||
private void addAll(boolean prepend, List<PropertySourceDescriptor> list, List<PropertySourceDescriptor> elements) {
|
||||
list.addAll((prepend ? 0 : list.size()), elements);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add all the supplied elements to the provided list, honoring the
|
||||
* {@code prepend} flag.
|
||||
|
@ -177,16 +204,18 @@ class TestPropertySourceAttributes {
|
|||
}
|
||||
|
||||
/**
|
||||
* Get the resource locations that were declared via {@code @TestPropertySource}.
|
||||
* Get the descriptors for resource locations that were declared via
|
||||
* {@code @TestPropertySource}.
|
||||
* <p>Note: The returned value may represent a <em>detected default</em>
|
||||
* or merged locations that do not match the original value declared via a
|
||||
* single {@code @TestPropertySource} annotation.
|
||||
* @return the resource locations; potentially <em>empty</em>
|
||||
* @return the resource location descriptors; potentially <em>empty</em>
|
||||
* @see TestPropertySource#value
|
||||
* @see TestPropertySource#locations
|
||||
* @see TestPropertySource#factory
|
||||
*/
|
||||
String[] getLocations() {
|
||||
return StringUtils.toStringArray(this.locations);
|
||||
List<PropertySourceDescriptor> getPropertySourceDescriptors() {
|
||||
return this.descriptors;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -220,7 +249,7 @@ class TestPropertySourceAttributes {
|
|||
}
|
||||
|
||||
boolean isEmpty() {
|
||||
return (this.locations.isEmpty() && this.properties.isEmpty());
|
||||
return (hasNoLocations(this.descriptors) && this.properties.isEmpty());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -233,7 +262,7 @@ class TestPropertySourceAttributes {
|
|||
}
|
||||
|
||||
TestPropertySourceAttributes that = (TestPropertySourceAttributes) other;
|
||||
if (!this.locations.equals(that.locations)) {
|
||||
if (!this.descriptors.equals(that.descriptors)) {
|
||||
return false;
|
||||
}
|
||||
if (!this.properties.equals(that.properties)) {
|
||||
|
@ -251,7 +280,7 @@ class TestPropertySourceAttributes {
|
|||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = this.locations.hashCode();
|
||||
int result = this.descriptors.hashCode();
|
||||
result = 31 * result + this.properties.hashCode();
|
||||
result = 31 * result + (this.inheritLocations ? 1231 : 1237);
|
||||
result = 31 * result + (this.inheritProperties ? 1231 : 1237);
|
||||
|
@ -265,8 +294,8 @@ class TestPropertySourceAttributes {
|
|||
@Override
|
||||
public String toString() {
|
||||
return new ToStringCreator(this, new DefaultToStringStyler(new SimpleValueStyler()))
|
||||
.append("declaringClass", this.declaringClass)
|
||||
.append("locations", this.locations)
|
||||
.append("declaringClass", this.declaringClass.getName())
|
||||
.append("descriptors", this.descriptors)
|
||||
.append("inheritLocations", this.inheritLocations)
|
||||
.append("properties", this.properties)
|
||||
.append("inheritProperties", this.inheritProperties)
|
||||
|
@ -279,4 +308,12 @@ class TestPropertySourceAttributes {
|
|||
return (Class<?>) source;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the supplied list contains no descriptor with locations.
|
||||
*/
|
||||
private static boolean hasNoLocations(List<PropertySourceDescriptor> descriptors) {
|
||||
return descriptors.stream().map(PropertySourceDescriptor::locations)
|
||||
.flatMap(List::stream).findAny().isEmpty();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -30,6 +30,7 @@ import java.util.Properties;
|
|||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.core.annotation.MergedAnnotation;
|
||||
import org.springframework.core.annotation.MergedAnnotations;
|
||||
|
@ -37,15 +38,18 @@ import org.springframework.core.annotation.MergedAnnotations.SearchStrategy;
|
|||
import org.springframework.core.env.ConfigurableEnvironment;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.core.env.MapPropertySource;
|
||||
import org.springframework.core.env.MutablePropertySources;
|
||||
import org.springframework.core.env.PropertySource;
|
||||
import org.springframework.core.env.PropertySources;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.io.ResourceLoader;
|
||||
import org.springframework.core.io.support.ResourcePropertySource;
|
||||
import org.springframework.core.io.support.DefaultPropertySourceFactory;
|
||||
import org.springframework.core.io.support.EncodedResource;
|
||||
import org.springframework.core.io.support.PropertySourceDescriptor;
|
||||
import org.springframework.core.io.support.PropertySourceFactory;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.test.context.TestContextAnnotationUtils;
|
||||
import org.springframework.test.context.TestPropertySource;
|
||||
import org.springframework.test.context.util.TestContextResourceUtils;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
@ -71,6 +75,8 @@ public abstract class TestPropertySourceUtils {
|
|||
*/
|
||||
public static final String INLINED_PROPERTIES_PROPERTY_SOURCE_NAME = "Inlined Test Properties";
|
||||
|
||||
private static final PropertySourceFactory defaultPropertySourceFactory = new DefaultPropertySourceFactory();
|
||||
|
||||
private static final Log logger = LogFactory.getLog(TestPropertySourceUtils.class);
|
||||
|
||||
|
||||
|
@ -139,20 +145,18 @@ public abstract class TestPropertySourceUtils {
|
|||
return duplicationDetected;
|
||||
}
|
||||
|
||||
private static String[] mergeLocations(List<TestPropertySourceAttributes> attributesList) {
|
||||
List<String> locations = new ArrayList<>();
|
||||
private static List<PropertySourceDescriptor> mergeLocations(List<TestPropertySourceAttributes> attributesList) {
|
||||
List<PropertySourceDescriptor> descriptors = new ArrayList<>();
|
||||
for (TestPropertySourceAttributes attrs : attributesList) {
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Processing locations for " + attrs);
|
||||
}
|
||||
String[] locationsArray = TestContextResourceUtils.convertToClasspathResourcePaths(
|
||||
attrs.getDeclaringClass(), true, attrs.getLocations());
|
||||
locations.addAll(0, Arrays.asList(locationsArray));
|
||||
descriptors.addAll(0, attrs.getPropertySourceDescriptors());
|
||||
if (!attrs.isInheritLocations()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return StringUtils.toStringArray(locations);
|
||||
return descriptors;
|
||||
}
|
||||
|
||||
private static String[] mergeProperties(List<TestPropertySourceAttributes> attributesList) {
|
||||
|
@ -181,9 +185,10 @@ public abstract class TestPropertySourceUtils {
|
|||
* to the environment; potentially empty but never {@code null}
|
||||
* @throws IllegalStateException if an error occurs while processing a properties file
|
||||
* @since 4.1.5
|
||||
* @see ResourcePropertySource
|
||||
* @see org.springframework.core.io.support.ResourcePropertySource
|
||||
* @see TestPropertySource#locations
|
||||
* @see #addPropertiesFilesToEnvironment(ConfigurableEnvironment, ResourceLoader, String...)
|
||||
* @see #addPropertySourcesToEnvironment(ConfigurableApplicationContext, List)
|
||||
*/
|
||||
public static void addPropertiesFilesToEnvironment(ConfigurableApplicationContext context, String... locations) {
|
||||
Assert.notNull(context, "'context' must not be null");
|
||||
|
@ -197,7 +202,8 @@ public abstract class TestPropertySourceUtils {
|
|||
* <p>Property placeholders in resource locations (i.e., <code>${...}</code>)
|
||||
* will be {@linkplain Environment#resolveRequiredPlaceholders(String) resolved}
|
||||
* against the {@code Environment}.
|
||||
* <p>Each properties file will be converted to a {@link ResourcePropertySource}
|
||||
* <p>Each properties file will be converted to a
|
||||
* {@link org.springframework.core.io.support.ResourcePropertySource ResourcePropertySource}
|
||||
* that will be added to the {@link PropertySources} of the environment with
|
||||
* the highest precedence.
|
||||
* @param environment the environment to update; never {@code null}
|
||||
|
@ -207,21 +213,95 @@ public abstract class TestPropertySourceUtils {
|
|||
* to the environment; potentially empty but never {@code null}
|
||||
* @throws IllegalStateException if an error occurs while processing a properties file
|
||||
* @since 4.3
|
||||
* @see ResourcePropertySource
|
||||
* @see org.springframework.core.io.support.ResourcePropertySource
|
||||
* @see TestPropertySource#locations
|
||||
* @see #addPropertiesFilesToEnvironment(ConfigurableApplicationContext, String...)
|
||||
* @see #addPropertySourcesToEnvironment(ConfigurableApplicationContext, List)
|
||||
*/
|
||||
public static void addPropertiesFilesToEnvironment(ConfigurableEnvironment environment,
|
||||
ResourceLoader resourceLoader, String... locations) {
|
||||
|
||||
Assert.notNull(locations, "'locations' must not be null");
|
||||
addPropertySourcesToEnvironment(environment, resourceLoader,
|
||||
List.of(new PropertySourceDescriptor(locations)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Add property sources for the given {@code descriptors} to the
|
||||
* {@link Environment} of the supplied {@code context}.
|
||||
* <p>Property placeholders in resource locations (i.e., <code>${...}</code>)
|
||||
* will be {@linkplain Environment#resolveRequiredPlaceholders(String) resolved}
|
||||
* against the {@code Environment}.
|
||||
* <p>Each {@link PropertySource} will be created via the configured
|
||||
* {@link PropertySourceDescriptor#propertySourceFactory() PropertySourceFactory}
|
||||
* (or the {@link DefaultPropertySourceFactory} if no factory is configured)
|
||||
* and added to the {@link PropertySources} of the environment with the highest
|
||||
* precedence.
|
||||
* @param context the application context whose environment should be updated;
|
||||
* never {@code null}
|
||||
* @param descriptors the property source descriptors to process; potentially
|
||||
* empty but never {@code null}
|
||||
* @throws IllegalStateException if an error occurs while processing the
|
||||
* descriptors and registering property sources
|
||||
* @since 6.1
|
||||
* @see TestPropertySource#locations
|
||||
* @see TestPropertySource#factory
|
||||
* @see PropertySourceFactory
|
||||
*/
|
||||
public static void addPropertySourcesToEnvironment(ConfigurableApplicationContext context,
|
||||
List<PropertySourceDescriptor> descriptors) {
|
||||
|
||||
Assert.notNull(context, "'context' must not be null");
|
||||
Assert.notNull(descriptors, "'descriptors' must not be null");
|
||||
addPropertySourcesToEnvironment(context.getEnvironment(), context, descriptors);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add property sources for the given {@code descriptors} to the supplied
|
||||
* {@link ConfigurableEnvironment environment}.
|
||||
* <p>Property placeholders in resource locations (i.e., <code>${...}</code>)
|
||||
* will be {@linkplain Environment#resolveRequiredPlaceholders(String) resolved}
|
||||
* against the {@code Environment}.
|
||||
* <p>Each {@link PropertySource} will be created via the configured
|
||||
* {@link PropertySourceDescriptor#propertySourceFactory() PropertySourceFactory}
|
||||
* (or the {@link DefaultPropertySourceFactory} if no factory is configured)
|
||||
* and added to the {@link PropertySources} of the environment with the highest
|
||||
* precedence.
|
||||
* @param environment the environment to update; never {@code null}
|
||||
* @param resourceLoader the {@code ResourceLoader} to use to load each resource;
|
||||
* never {@code null}
|
||||
* @param descriptors the property source descriptors to process; potentially
|
||||
* empty but never {@code null}
|
||||
* @throws IllegalStateException if an error occurs while processing the
|
||||
* descriptors and registering property sources
|
||||
* @since 6.1
|
||||
* @see TestPropertySource#locations
|
||||
* @see TestPropertySource#factory
|
||||
* @see PropertySourceFactory
|
||||
*/
|
||||
private static void addPropertySourcesToEnvironment(ConfigurableEnvironment environment,
|
||||
ResourceLoader resourceLoader, List<PropertySourceDescriptor> descriptors) {
|
||||
|
||||
Assert.notNull(environment, "'environment' must not be null");
|
||||
Assert.notNull(resourceLoader, "'resourceLoader' must not be null");
|
||||
Assert.notNull(locations, "'locations' must not be null");
|
||||
Assert.notNull(descriptors, "'descriptors' must not be null");
|
||||
MutablePropertySources propertySources = environment.getPropertySources();
|
||||
try {
|
||||
for (String location : locations) {
|
||||
String resolvedLocation = environment.resolveRequiredPlaceholders(location);
|
||||
Resource resource = resourceLoader.getResource(resolvedLocation);
|
||||
environment.getPropertySources().addFirst(new ResourcePropertySource(resource));
|
||||
for (PropertySourceDescriptor descriptor : descriptors) {
|
||||
if (!descriptor.locations().isEmpty()) {
|
||||
Class<? extends PropertySourceFactory> factoryClass = descriptor.propertySourceFactory();
|
||||
PropertySourceFactory factory =
|
||||
(factoryClass != null && factoryClass != PropertySourceFactory.class ?
|
||||
BeanUtils.instantiateClass(factoryClass) : defaultPropertySourceFactory);
|
||||
|
||||
for (String location : descriptor.locations()) {
|
||||
String resolvedLocation = environment.resolveRequiredPlaceholders(location);
|
||||
Resource resource = resourceLoader.getResource(resolvedLocation);
|
||||
PropertySource<?> propertySource = factory.createPropertySource(descriptor.name(),
|
||||
new EncodedResource(resource, descriptor.encoding()));
|
||||
propertySources.addFirst(propertySource);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (IOException ex) {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -16,9 +16,11 @@
|
|||
|
||||
package org.springframework.test.context.web;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.context.ApplicationContextInitializer;
|
||||
import org.springframework.core.io.support.PropertySourceDescriptor;
|
||||
import org.springframework.core.style.DefaultToStringStyler;
|
||||
import org.springframework.core.style.SimpleValueStyler;
|
||||
import org.springframework.core.style.ToStringCreator;
|
||||
|
@ -99,7 +101,10 @@ public class WebMergedContextConfiguration extends MergedContextConfiguration {
|
|||
* delegate with which to retrieve the parent context
|
||||
* @param parent the parent configuration or {@code null} if there is no parent
|
||||
* @since 4.1
|
||||
* @deprecated since 6.1 in favor of
|
||||
* {@link #WebMergedContextConfiguration(Class, String[], Class[], Set, String[], List, String[], Set, String, ContextLoader, CacheAwareContextLoaderDelegate, MergedContextConfiguration)}
|
||||
*/
|
||||
@Deprecated(since = "6.1")
|
||||
public WebMergedContextConfiguration(Class<?> testClass, @Nullable String[] locations, @Nullable Class<?>[] classes,
|
||||
@Nullable Set<Class<? extends ApplicationContextInitializer<?>>> contextInitializerClasses,
|
||||
@Nullable String[] activeProfiles, @Nullable String[] propertySourceLocations, @Nullable String[] propertySourceProperties,
|
||||
|
@ -135,14 +140,54 @@ public class WebMergedContextConfiguration extends MergedContextConfiguration {
|
|||
* delegate with which to retrieve the parent context
|
||||
* @param parent the parent configuration or {@code null} if there is no parent
|
||||
* @since 4.3
|
||||
* @deprecated since 6.1 in favor of
|
||||
* {@link #WebMergedContextConfiguration(Class, String[], Class[], Set, String[], List, String[], Set, String, ContextLoader, CacheAwareContextLoaderDelegate, MergedContextConfiguration)}
|
||||
*/
|
||||
@Deprecated(since = "6.1")
|
||||
public WebMergedContextConfiguration(Class<?> testClass, @Nullable String[] locations, @Nullable Class<?>[] classes,
|
||||
@Nullable Set<Class<? extends ApplicationContextInitializer<?>>> contextInitializerClasses,
|
||||
@Nullable String[] activeProfiles, @Nullable String[] propertySourceLocations, @Nullable String[] propertySourceProperties,
|
||||
@Nullable Set<ContextCustomizer> contextCustomizers, String resourceBasePath, ContextLoader contextLoader,
|
||||
CacheAwareContextLoaderDelegate cacheAwareContextLoaderDelegate, @Nullable MergedContextConfiguration parent) {
|
||||
|
||||
super(testClass, locations, classes, contextInitializerClasses, activeProfiles, propertySourceLocations,
|
||||
this(testClass, locations, classes, contextInitializerClasses, activeProfiles,
|
||||
List.of(new PropertySourceDescriptor(processStrings(propertySourceLocations))),
|
||||
propertySourceProperties, contextCustomizers, resourceBasePath, contextLoader,
|
||||
cacheAwareContextLoaderDelegate, parent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@code WebMergedContextConfiguration} instance for the supplied
|
||||
* parameters.
|
||||
* <p>If a {@code null} value is supplied for {@code locations}, {@code classes},
|
||||
* {@code activeProfiles}, or {@code propertySourceProperties} an empty array
|
||||
* will be stored instead. If a {@code null} value is supplied for
|
||||
* {@code contextInitializerClasses} or {@code contextCustomizers}, an empty
|
||||
* set will be stored instead. Furthermore, active profiles will be sorted,
|
||||
* and duplicate profiles will be removed.
|
||||
* @param testClass the test class for which the configuration was merged
|
||||
* @param locations the merged context resource locations
|
||||
* @param classes the merged annotated classes
|
||||
* @param contextInitializerClasses the merged context initializer classes
|
||||
* @param activeProfiles the merged active bean definition profiles
|
||||
* @param propertySourceDescriptors the merged property source descriptors
|
||||
* @param propertySourceProperties the merged inlined properties
|
||||
* @param contextCustomizers the context customizers
|
||||
* @param resourceBasePath the resource path to the root directory of the web application
|
||||
* @param contextLoader the resolved {@code ContextLoader}
|
||||
* @param cacheAwareContextLoaderDelegate a cache-aware context loader
|
||||
* delegate with which to retrieve the parent {@code ApplicationContext}
|
||||
* @param parent the parent configuration or {@code null} if there is no parent
|
||||
* @since 6.1
|
||||
*/
|
||||
public WebMergedContextConfiguration(Class<?> testClass, @Nullable String[] locations, @Nullable Class<?>[] classes,
|
||||
@Nullable Set<Class<? extends ApplicationContextInitializer<?>>> contextInitializerClasses,
|
||||
@Nullable String[] activeProfiles,
|
||||
List<PropertySourceDescriptor> propertySourceDescriptors, @Nullable String[] propertySourceProperties,
|
||||
@Nullable Set<ContextCustomizer> contextCustomizers, String resourceBasePath, ContextLoader contextLoader,
|
||||
CacheAwareContextLoaderDelegate cacheAwareContextLoaderDelegate, @Nullable MergedContextConfiguration parent) {
|
||||
|
||||
super(testClass, locations, classes, contextInitializerClasses, activeProfiles, propertySourceDescriptors,
|
||||
propertySourceProperties, contextCustomizers, contextLoader, cacheAwareContextLoaderDelegate, parent);
|
||||
|
||||
this.resourceBasePath = (StringUtils.hasText(resourceBasePath) ? resourceBasePath : "");
|
||||
|
@ -160,11 +205,14 @@ public class WebMergedContextConfiguration extends MergedContextConfiguration {
|
|||
|
||||
/**
|
||||
* Determine if the supplied object is equal to this {@code WebMergedContextConfiguration}
|
||||
* instance by comparing both object's {@linkplain #getLocations() locations},
|
||||
* instance by comparing both objects' {@linkplain #getLocations() locations},
|
||||
* {@linkplain #getClasses() annotated classes},
|
||||
* {@linkplain #getContextInitializerClasses() context initializer classes},
|
||||
* {@linkplain #getActiveProfiles() active profiles},
|
||||
* {@linkplain #getResourceBasePath() resource base path},
|
||||
* {@linkplain #getResourceBasePath() resource base paths},
|
||||
* {@linkplain #getPropertySourceDescriptors() property source descriptors},
|
||||
* {@linkplain #getPropertySourceProperties() property source properties},
|
||||
* {@linkplain #getContextCustomizers() context customizers},
|
||||
* {@linkplain #getParent() parents}, and the fully qualified names of their
|
||||
* {@link #getContextLoader() ContextLoaders}.
|
||||
*/
|
||||
|
@ -189,7 +237,7 @@ public class WebMergedContextConfiguration extends MergedContextConfiguration {
|
|||
* {@linkplain #getLocations() locations}, {@linkplain #getClasses() annotated classes},
|
||||
* {@linkplain #getContextInitializerClasses() context initializer classes},
|
||||
* {@linkplain #getActiveProfiles() active profiles},
|
||||
* {@linkplain #getPropertySourceLocations() property source locations},
|
||||
* {@linkplain #getPropertySourceDescriptors() property source descriptors},
|
||||
* {@linkplain #getPropertySourceProperties() property source properties},
|
||||
* {@linkplain #getContextCustomizers() context customizers},
|
||||
* {@linkplain #getResourceBasePath() resource base path}, the name of the
|
||||
|
@ -204,7 +252,7 @@ public class WebMergedContextConfiguration extends MergedContextConfiguration {
|
|||
.append("classes", getClasses())
|
||||
.append("contextInitializerClasses", getContextInitializerClasses())
|
||||
.append("activeProfiles", getActiveProfiles())
|
||||
.append("propertySourceLocations", getPropertySourceLocations())
|
||||
.append("propertySourceDescriptors", getPropertySourceDescriptors())
|
||||
.append("propertySourceProperties", getPropertySourceProperties())
|
||||
.append("contextCustomizers", getContextCustomizers())
|
||||
.append("resourceBasePath", getResourceBasePath())
|
||||
|
|
|
@ -18,6 +18,7 @@ package org.springframework.test.context;
|
|||
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
@ -409,9 +410,9 @@ class MergedContextConfigurationTests {
|
|||
void equalsWithSameContextCustomizers() {
|
||||
Set<ContextCustomizer> customizers = Collections.singleton(mock());
|
||||
MergedContextConfiguration mergedConfig1 = new MergedContextConfiguration(getClass(), EMPTY_STRING_ARRAY,
|
||||
EMPTY_CLASS_ARRAY, null, EMPTY_STRING_ARRAY, null, null, customizers, loader, null, null);
|
||||
EMPTY_CLASS_ARRAY, null, EMPTY_STRING_ARRAY, List.of(), null, customizers, loader, null, null);
|
||||
MergedContextConfiguration mergedConfig2 = new MergedContextConfiguration(getClass(), EMPTY_STRING_ARRAY,
|
||||
EMPTY_CLASS_ARRAY, null, EMPTY_STRING_ARRAY, null, null, customizers, loader, null, null);
|
||||
EMPTY_CLASS_ARRAY, null, EMPTY_STRING_ARRAY, List.of(), null, customizers, loader, null, null);
|
||||
assertThat(mergedConfig2).isEqualTo(mergedConfig1);
|
||||
}
|
||||
|
||||
|
@ -424,9 +425,9 @@ class MergedContextConfigurationTests {
|
|||
Set<ContextCustomizer> customizers2 = Collections.singleton(mock());
|
||||
|
||||
MergedContextConfiguration mergedConfig1 = new MergedContextConfiguration(getClass(), EMPTY_STRING_ARRAY,
|
||||
EMPTY_CLASS_ARRAY, null, EMPTY_STRING_ARRAY, null, null, customizers1, loader, null, null);
|
||||
EMPTY_CLASS_ARRAY, null, EMPTY_STRING_ARRAY, List.of(), null, customizers1, loader, null, null);
|
||||
MergedContextConfiguration mergedConfig2 = new MergedContextConfiguration(getClass(), EMPTY_STRING_ARRAY,
|
||||
EMPTY_CLASS_ARRAY, null, EMPTY_STRING_ARRAY, null, null, customizers2, loader, null, null);
|
||||
EMPTY_CLASS_ARRAY, null, EMPTY_STRING_ARRAY, List.of(), null, customizers2, loader, null, null);
|
||||
assertThat(mergedConfig2).isNotEqualTo(mergedConfig1);
|
||||
assertThat(mergedConfig1).isNotEqualTo(mergedConfig2);
|
||||
}
|
||||
|
|
62
spring-test/src/test/java/org/springframework/test/context/env/YamlPropertySourceFactory.java
vendored
Normal file
62
spring-test/src/test/java/org/springframework/test/context/env/YamlPropertySourceFactory.java
vendored
Normal file
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.test.context.env;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
import org.springframework.beans.factory.config.YamlPropertiesFactoryBean;
|
||||
import org.springframework.core.env.PropertiesPropertySource;
|
||||
import org.springframework.core.env.PropertySource;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.io.support.EncodedResource;
|
||||
import org.springframework.core.io.support.PropertySourceFactory;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Demo {@link PropertySourceFactory} that provides YAML support.
|
||||
*
|
||||
* @author Sam Brannen
|
||||
* @since 6.1
|
||||
*/
|
||||
class YamlPropertySourceFactory implements PropertySourceFactory {
|
||||
|
||||
@Override
|
||||
public PropertySource<?> createPropertySource(String name, EncodedResource encodedResource) {
|
||||
Resource resource = encodedResource.getResource();
|
||||
if (!StringUtils.hasText(name)) {
|
||||
name = getNameForResource(resource);
|
||||
}
|
||||
YamlPropertiesFactoryBean factoryBean = new YamlPropertiesFactoryBean();
|
||||
factoryBean.setResources(resource);
|
||||
factoryBean.afterPropertiesSet();
|
||||
Properties properties = factoryBean.getObject();
|
||||
return new PropertiesPropertySource(name, properties);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the description for the given Resource; if the description is
|
||||
* empty, return the class name of the resource plus its identity hash code.
|
||||
*/
|
||||
private static String getNameForResource(Resource resource) {
|
||||
String name = resource.getDescription();
|
||||
if (!StringUtils.hasText(name)) {
|
||||
name = resource.getClass().getSimpleName() + "@" + System.identityHashCode(resource);
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
}
|
39
spring-test/src/test/java/org/springframework/test/context/env/YamlTestProperties.java
vendored
Normal file
39
spring-test/src/test/java/org/springframework/test/context/env/YamlTestProperties.java
vendored
Normal file
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.test.context.env;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import org.springframework.core.annotation.AliasFor;
|
||||
import org.springframework.test.context.TestPropertySource;
|
||||
|
||||
/**
|
||||
* @author Sam Brannen
|
||||
* @since 6.1
|
||||
*/
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@TestPropertySource(factory = YamlPropertySourceFactory.class)
|
||||
public @interface YamlTestProperties {
|
||||
|
||||
@AliasFor(annotation = TestPropertySource.class)
|
||||
String[] value();
|
||||
|
||||
}
|
59
spring-test/src/test/java/org/springframework/test/context/env/YamlTestPropertySourceTests.java
vendored
Normal file
59
spring-test/src/test/java/org/springframework/test/context/env/YamlTestPropertySourceTests.java
vendored
Normal file
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.test.context.env;
|
||||
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.CsvSource;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.env.ConfigurableEnvironment;
|
||||
import org.springframework.core.io.support.PropertySourceFactory;
|
||||
import org.springframework.test.context.TestPropertySource;
|
||||
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link TestPropertySource @TestPropertySource} support
|
||||
* with a custom YAML {@link PropertySourceFactory}.
|
||||
*
|
||||
* @author Sam Brannen
|
||||
* @since 6.1
|
||||
*/
|
||||
@SpringJUnitConfig
|
||||
@YamlTestProperties("test-properties.yaml")
|
||||
class YamlTestPropertySourceTests {
|
||||
|
||||
@ParameterizedTest
|
||||
@CsvSource(delimiterString = "->", textBlock = """
|
||||
environments.dev.url -> https://dev.example.com
|
||||
environments.dev.name -> 'Developer Setup'
|
||||
environments.prod.url -> https://prod.example.com
|
||||
environments.prod.name -> 'My Cool App'
|
||||
""")
|
||||
void propertyIsAvailableInEnvironment(String property, String value, @Autowired ConfigurableEnvironment env) {
|
||||
assertThat(env.getProperty(property)).isEqualTo(value);
|
||||
}
|
||||
|
||||
|
||||
@Configuration
|
||||
static class Config {
|
||||
/* no user beans required for these tests */
|
||||
}
|
||||
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -16,15 +16,9 @@
|
|||
|
||||
package org.springframework.test.context.env.repeatable;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.test.context.TestPropertySource;
|
||||
import org.springframework.test.context.env.repeatable.LocalPropertiesFileAndMetaPropertiesFileTests.MetaFileTestProperty;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link TestPropertySource @TestPropertySource} as a
|
||||
|
@ -48,15 +42,4 @@ class LocalPropertiesFileAndMetaPropertiesFileTests extends AbstractRepeatableTe
|
|||
assertEnvironmentValue("key2", "meta file");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Composed annotation that declares a properties file via
|
||||
* {@link TestPropertySource @TestPropertySource}.
|
||||
*/
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@TestPropertySource("meta.properties")
|
||||
@interface MetaFileTestProperty {
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.test.context.env.repeatable;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.test.context.env.YamlTestProperties;
|
||||
|
||||
/**
|
||||
* Analogous to {@link LocalPropertiesFileAndMetaPropertiesFileTests} except
|
||||
* that the local file is YAML.
|
||||
*
|
||||
* @author Sam Brannen
|
||||
* @since 6.1
|
||||
*/
|
||||
@YamlTestProperties("local.yaml")
|
||||
@MetaFileTestProperty
|
||||
class LocalYamlFileAndMetaPropertiesFileTests extends AbstractRepeatableTestPropertySourceTests {
|
||||
|
||||
@Test
|
||||
void test() {
|
||||
assertEnvironmentValue("key1", "local file");
|
||||
assertEnvironmentValue("key2", "meta file");
|
||||
|
||||
assertEnvironmentValue("environments.dev.url", "https://dev.example.com");
|
||||
assertEnvironmentValue("environments.dev.name", "Developer Setup");
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.test.context.env.repeatable;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import org.springframework.test.context.TestPropertySource;
|
||||
|
||||
/**
|
||||
* Composed annotation that declares a properties file via
|
||||
* {@link TestPropertySource @TestPropertySource}.
|
||||
*/
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@TestPropertySource("meta.properties")
|
||||
@interface MetaFileTestProperty {
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -187,6 +187,7 @@ class BootstrapTestUtilsMergedConfigTests extends AbstractContextConfigurationUt
|
|||
assertMergedConfigForLocationPaths(RelativeFooXmlLocation.class);
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
private void assertMergedConfigForLocationPaths(Class<?> testClass) {
|
||||
MergedContextConfiguration mergedConfig = buildMergedContextConfiguration(testClass);
|
||||
|
||||
|
|
|
@ -18,7 +18,9 @@ package org.springframework.test.context.support;
|
|||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.assertj.core.api.SoftAssertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
@ -29,6 +31,7 @@ import org.springframework.core.env.ConfigurableEnvironment;
|
|||
import org.springframework.core.env.MutablePropertySources;
|
||||
import org.springframework.core.io.ByteArrayResource;
|
||||
import org.springframework.core.io.ResourceLoader;
|
||||
import org.springframework.core.io.support.PropertySourceDescriptor;
|
||||
import org.springframework.mock.env.MockEnvironment;
|
||||
import org.springframework.mock.env.MockPropertySource;
|
||||
import org.springframework.test.context.TestPropertySource;
|
||||
|
@ -295,7 +298,9 @@ class TestPropertySourceUtilsTests {
|
|||
MergedTestPropertySources mergedPropertySources = buildMergedTestPropertySources(testClass);
|
||||
SoftAssertions.assertSoftly(softly -> {
|
||||
softly.assertThat(mergedPropertySources).isNotNull();
|
||||
softly.assertThat(mergedPropertySources.getLocations()).isEqualTo(expectedLocations);
|
||||
Stream<String> locations = mergedPropertySources.getPropertySourceDescriptors().stream()
|
||||
.map(PropertySourceDescriptor::locations).flatMap(List::stream);
|
||||
softly.assertThat(locations).containsExactly(expectedLocations);
|
||||
softly.assertThat(mergedPropertySources.getProperties()).isEqualTo(expectedProperties);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -33,14 +33,15 @@ class AnnotationConfigWebContextLoaderTests {
|
|||
|
||||
|
||||
@Test
|
||||
void configMustNotContainLocations() throws Exception {
|
||||
@SuppressWarnings("deprecation")
|
||||
void configMustNotContainLocations() {
|
||||
AnnotationConfigWebContextLoader loader = new AnnotationConfigWebContextLoader();
|
||||
WebMergedContextConfiguration mergedConfig = new WebMergedContextConfiguration(getClass(),
|
||||
new String[] { "config.xml" }, EMPTY_CLASS_ARRAY, null, EMPTY_STRING_ARRAY, EMPTY_STRING_ARRAY,
|
||||
EMPTY_STRING_ARRAY, "resource/path", loader, null, null);
|
||||
assertThatIllegalStateException()
|
||||
.isThrownBy(() -> loader.loadContext(mergedConfig))
|
||||
.withMessageContaining("does not support resource locations");
|
||||
.isThrownBy(() -> loader.loadContext(mergedConfig))
|
||||
.withMessageContaining("does not support resource locations");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -34,12 +34,13 @@ class GenericXmlWebContextLoaderTests {
|
|||
@Test
|
||||
void configMustNotContainAnnotatedClasses() throws Exception {
|
||||
GenericXmlWebContextLoader loader = new GenericXmlWebContextLoader();
|
||||
@SuppressWarnings("deprecation")
|
||||
WebMergedContextConfiguration mergedConfig = new WebMergedContextConfiguration(getClass(), EMPTY_STRING_ARRAY,
|
||||
new Class<?>[] { getClass() }, null, EMPTY_STRING_ARRAY, EMPTY_STRING_ARRAY, EMPTY_STRING_ARRAY,
|
||||
"resource/path", loader, null, null);
|
||||
assertThatIllegalStateException()
|
||||
.isThrownBy(() -> loader.loadContext(mergedConfig))
|
||||
.withMessageContaining("does not support annotated classes");
|
||||
.isThrownBy(() -> loader.loadContext(mergedConfig))
|
||||
.withMessageContaining("does not support annotated classes");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
5
spring-test/src/test/resources/org/springframework/test/context/env/repeatable/local.yaml
vendored
Normal file
5
spring-test/src/test/resources/org/springframework/test/context/env/repeatable/local.yaml
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
key1: local file
|
||||
environments:
|
||||
dev:
|
||||
url: https://dev.example.com
|
||||
name: Developer Setup
|
7
spring-test/src/test/resources/org/springframework/test/context/env/test-properties.yaml
vendored
Normal file
7
spring-test/src/test/resources/org/springframework/test/context/env/test-properties.yaml
vendored
Normal file
|
@ -0,0 +1,7 @@
|
|||
environments:
|
||||
dev:
|
||||
url: https://dev.example.com
|
||||
name: Developer Setup
|
||||
prod:
|
||||
url: https://prod.example.com
|
||||
name: My Cool App
|
Loading…
Reference in New Issue