Skip to content
Permalink
Browse files

Merge branch 'sbrannen/issues/gh-23320-repeatable-TestPropertySource'

  • Loading branch information...
sbrannen committed Jul 27, 2019
2 parents 8574f97 + 1075bae commit 690694df33151f5d003462b14026ef3fda57e010
Showing with 943 additions and 129 deletions.
  1. +5 −1 spring-test/src/main/java/org/springframework/test/context/TestPropertySource.java
  2. +50 −0 spring-test/src/main/java/org/springframework/test/context/TestPropertySources.java
  3. +26 −56 spring-test/src/main/java/org/springframework/test/context/support/TestPropertySourceAttributes.java
  4. +146 −33 spring-test/src/main/java/org/springframework/test/context/support/TestPropertySourceUtils.java
  5. +44 −0 spring-test/src/test/java/org/springframework/test/context/env/TestPropertySourceTestSuite.java
  6. +31 −0 .../src/test/java/org/springframework/test/context/env/repeatable/AbstractClassWithTestProperty.java
  7. +54 −0 ...va/org/springframework/test/context/env/repeatable/AbstractRepeatableTestPropertySourceTests.java
  8. +42 −0 ...rk/test/context/env/repeatable/DefaultPropertiesFileDetectionRepeatedTestPropertySourceTests.java
  9. +45 −0 ...framework/test/context/env/repeatable/ExplicitPropertiesFilesRepeatedTestPropertySourceTests.java
  10. +40 −0 ...ngframework/test/context/env/repeatable/LocalInlinedPropertyAndInheritedInlinedPropertyTests.java
  11. +41 −0 .../springframework/test/context/env/repeatable/LocalInlinedPropertyAndMetaInlinedPropertyTests.java
  12. +52 −0 ...t/context/env/repeatable/LocalInlinedPropertyOverridesInheritedAndMetaInlinedPropertiesTests.java
  13. +43 −0 ...ework/test/context/env/repeatable/LocalInlinedPropertyOverridesInheritedInlinedPropertyTests.java
  14. +40 −0 ...gframework/test/context/env/repeatable/LocalInlinedPropertyOverridesMetaInlinedPropertyTests.java
  15. +62 −0 ...rg/springframework/test/context/env/repeatable/LocalPropertiesFileAndMetaPropertiesFileTests.java
  16. +37 −0 ...g-test/src/test/java/org/springframework/test/context/env/repeatable/MetaInlinedTestProperty.java
  17. +43 −0 ...rc/test/java/org/springframework/test/context/env/repeatable/RepeatedTestPropertySourceTests.java
  18. +41 −0 ...k/test/context/env/repeatable/ReversedExplicitPropertiesFilesRepeatedTestPropertySourceTests.java
  19. +73 −39 spring-test/src/test/java/org/springframework/test/context/support/TestPropertySourceUtilsTests.java
  20. +1 −0 spring-test/src/test/resources/log4j2-test.xml
  21. +1 −0 ...t/context/env/repeatable/DefaultPropertiesFileDetectionRepeatedTestPropertySourceTests.properties
  22. +3 −0 spring-test/src/test/resources/org/springframework/test/context/env/repeatable/first.properties
  23. +1 −0 spring-test/src/test/resources/org/springframework/test/context/env/repeatable/local.properties
  24. +1 −0 spring-test/src/test/resources/org/springframework/test/context/env/repeatable/meta.properties
  25. +2 −0 spring-test/src/test/resources/org/springframework/test/context/env/repeatable/second.properties
  26. +19 −0 src/docs/asciidoc/testing.adoc
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* Copyright 2002-2019 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.
@@ -19,6 +19,7 @@
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@@ -67,6 +68,8 @@
* <ul>
* <li>Typically, {@code @TestPropertySource} will be used in conjunction with
* {@link ContextConfiguration @ContextConfiguration}.</li>
* <li>As of Spring Framework 5.2, {@code @TestPropertySource} can be used as a
* <em>{@linkplain Repeatable repeatable}</em> annotation.</li>
* <li>This annotation may be used as a <em>meta-annotation</em> to create
* custom <em>composed annotations</em>; however, caution should be taken if
* this annotation and {@code @ContextConfiguration} are combined on a composed
@@ -86,6 +89,7 @@
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Repeatable(TestPropertySources.class)
public @interface TestPropertySource {

/**
@@ -0,0 +1,50 @@
/*
* Copyright 2002-2019 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;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
* {@code @TestPropertySources} is a container for one or more
* {@link TestPropertySource @TestPropertySource} declarations.
*
* <p>Note, however, that use of the {@code @TestPropertySources} container is
* completely optional since {@code @TestPropertySource} is a
* {@linkplain java.lang.annotation.Repeatable repeatable} annotation.
*
* @author Anatoliy Korovin
* @author Sam Brannen
* @since 5.2
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface TestPropertySources {

/**
* An array of one or more {@link TestPropertySource @TestPropertySource}
* declarations.
*/
TestPropertySource[] value();

}
@@ -16,25 +16,19 @@

package org.springframework.test.context.support;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import java.util.List;

import org.springframework.core.io.ClassPathResource;
import org.springframework.core.style.ToStringCreator;
import org.springframework.lang.Nullable;
import org.springframework.test.context.TestPropertySource;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.ResourceUtils;

/**
* {@code TestPropertySourceAttributes} encapsulates the attributes declared
* via {@link TestPropertySource @TestPropertySource}.
* {@code TestPropertySourceAttributes} encapsulates attributes declared
* via {@link TestPropertySource @TestPropertySource} annotations.
*
* <p>In addition to encapsulating declared attributes,
* {@code TestPropertySourceAttributes} also enforces configuration rules
* and detects default properties files.
* {@code TestPropertySourceAttributes} also enforces configuration rules.
*
* @author Sam Brannen
* @since 4.1
@@ -43,8 +37,6 @@
*/
class TestPropertySourceAttributes {

private static final Log logger = LogFactory.getLog(TestPropertySourceAttributes.class);

private final Class<?> declaringClass;

private final String[] locations;
@@ -57,27 +49,29 @@


/**
* Create a new {@code TestPropertySourceAttributes} instance for the
* supplied {@link TestPropertySource @TestPropertySource} annotation and
* the {@linkplain Class test class} that declared it, enforcing
* configuration rules and detecting a default properties file if
* necessary.
* Create a new {@code TestPropertySourceAttributes} instance for the supplied
* values and enforce configuration rules.
* @param declaringClass the class that declared {@code @TestPropertySource}
* @param testPropertySource the annotation from which to retrieve the attributes
* @since 4.2
* @param locations the merged {@link TestPropertySource#locations()}
* @param inheritLocations the {@link TestPropertySource#inheritLocations()} flag
* @param properties the merged {@link TestPropertySource#properties()}
* @param inheritProperties the {@link TestPropertySource#inheritProperties()} flag
* @since 5.2
*/
TestPropertySourceAttributes(Class<?> declaringClass, TestPropertySource testPropertySource) {
this(declaringClass, testPropertySource.locations(), testPropertySource.inheritLocations(),
testPropertySource.properties(), testPropertySource.inheritProperties());
TestPropertySourceAttributes(Class<?> declaringClass, List<String> locations, boolean inheritLocations,
List<String> properties, boolean inheritProperties) {

this(declaringClass, locations.toArray(new String[0]), inheritLocations, properties.toArray(new String[0]),
inheritProperties);
}

private TestPropertySourceAttributes(Class<?> declaringClass, String[] locations, boolean inheritLocations,
String[] properties, boolean inheritProperties) {

Assert.notNull(declaringClass, "declaringClass must not be null");
if (ObjectUtils.isEmpty(locations) && ObjectUtils.isEmpty(properties)) {
locations = new String[] { detectDefaultPropertiesFile(declaringClass) };
}
Assert.notNull(declaringClass, "'declaringClass' must not be null");
Assert.isTrue(!ObjectUtils.isEmpty(locations) || !ObjectUtils.isEmpty(properties),
"Either 'locations' or 'properties' are required");

this.declaringClass = declaringClass;
this.locations = locations;
this.inheritLocations = inheritLocations;
@@ -97,7 +91,8 @@ private TestPropertySourceAttributes(Class<?> declaringClass, String[] locations
/**
* Get the resource locations that were declared via {@code @TestPropertySource}.
* <p>Note: The returned value may represent a <em>detected default</em>
* that does not match the original value declared via {@code @TestPropertySource}.
* 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>
* @see TestPropertySource#value
* @see TestPropertySource#locations
@@ -117,10 +112,12 @@ boolean isInheritLocations() {

/**
* Get the inlined properties that were declared via {@code @TestPropertySource}.
* @return the inlined properties; potentially {@code null} or <em>empty</em>
* <p>Note: The returned value may represent merged properties that do not
* match the original value declared via a single {@code @TestPropertySource}
* annotation.
* @return the inlined properties; potentially <em>empty</em>
* @see TestPropertySource#properties
*/
@Nullable
String[] getProperties() {
return this.properties;
}
@@ -149,31 +146,4 @@ public String toString() {
.toString();
}


/**
* Detect a default properties file for the supplied class, as specified
* in the class-level Javadoc for {@link TestPropertySource}.
*/
private static String detectDefaultPropertiesFile(Class<?> testClass) {
String resourcePath = ClassUtils.convertClassNameToResourcePath(testClass.getName()) + ".properties";
ClassPathResource classPathResource = new ClassPathResource(resourcePath);

if (classPathResource.exists()) {
String prefixedResourcePath = ResourceUtils.CLASSPATH_URL_PREFIX + resourcePath;
if (logger.isInfoEnabled()) {
logger.info(String.format("Detected default properties file \"%s\" for test class [%s]",
prefixedResourcePath, testClass.getName()));
}
return prefixedResourcePath;
}
else {
String msg = String.format("Could not detect default properties file for test [%s]: " +
"%s does not exist. Either declare the 'locations' or 'properties' attributes " +
"of @TestPropertySource or make the default properties file available.", testClass.getName(),
classPathResource);
logger.error(msg);
throw new IllegalStateException(msg);
}
}

}

0 comments on commit 690694d

Please sign in to comment.
You can’t perform that action at this time.