Prior to this commit, it was impossible to use all features of XML
configuration (e.g., the <qualifier> tag) in web-based integration
tests (loaded using @WebAppConfiguration, @ContextConfiguration, etc.)
if the Groovy library was on the classpath. The reason is that the
GroovyBeanDefinitionReader used internally by
GenericGroovyXmlWebContextLoader disables XML validation for its
internal XmlBeanDefinitionReader, and this prevents some XML
configuration features from working properly. For example, the default
value for the 'type' attribute (defined in the spring-beans XSD) of the
<qualifier> tag gets ignored, resulting in an exception when the
application context is loaded.
This commit addresses this issue by refactoring the implementation of
loadBeanDefinitions() in GenericGroovyXmlWebContextLoader to use an
XmlBeanDefinitionReader or GroovyBeanDefinitionReader depending on the
file extension of the resource location from which bean definitions
should be loaded. This aligns the functionality of
GenericGroovyXmlWebContextLoader with the existing functionality of
GenericGroovyXmlContextLoader.
Issue: SPR-12768
(cherry picked from commit 2ba1151b7fa3fcd3b0c964fc377ce57671eabb8b)
- Added assertions for pre-conditions on method arguments for all
public utility methods.
- Introduced additional tests in TestPropertySourceUtilsTests to verify
the new pre-conditions.
- Introduced INLINED_PROPERTIES_PROPERTY_SOURCE_NAME constant for the
name of the MapPropertySource created from inlined properties; the
name therefore no longer contains the inlined properties, but the
original values of the inlined properties can now be logged at debug
level.
- Simplified tests in InlinedPropertiesTestPropertySourceTests.
Issue: SPR-12721
(cherry picked from commit 42af33034d84327340e4bd53ec3f6c5bba626069)
Spring Framework 4.1 introduced support for @TestPropertySource;
however, the utilities used to parse inlined properties and add test
property sources to the environment are currently private which
prevents reuse by third-party frameworks like Spring Boot.
This commit addresses this issue by making such utilities public.
- TestPropertySourceUtils is now a public class.
- Various utility methods in TestPropertySourceUtils have been made
public.
- addResourcePropertySourcesToEnvironment() has been renamed to
addPropertiesFilesToEnvironment().
- extractEnvironmentProperties() has been renamed to
convertInlinedPropertiesToMap().
- All public methods in TestPropertySourceUtils are now fully
documented.
Issue: SPR-12721
(cherry picked from commit 75e0bc9271e6d5089f6c47f81114d58d09383c7d)
The initial implementation for adding inlined properties configured via
@TestPropertySource to the context's environment did not preserve the
order in which the properties were physically declared. This makes
@TestPropertySource a poor testing facility for mimicking the
production environment's configuration if the property source mechanism
used in production preserves ordering of property names -- which is the
case for YAML-based property sources used in Spring Boot, Spring Yarn,
etc.
This commit addresses this issue by ensuring that the ordering of
inlined properties declared via @TestPropertySource is preserved.
Specifically, the original functionality has been refactored. extracted
from AbstractContextLoader, and moved to TestPropertySourceUtils where
it may later be made public for general purpose use in other frameworks.
Issue: SPR-12710
(cherry picked from commit d6a799ad4af81da8840fbd5536efd49b9225ef8a)
This commit introduces further regression tests to ensure proper parsing
of inlined properties configured via @TestPropertySource. Specifically,
these additional tests ensure that we do not introduce a bug like the
one raised in Spring Boot issue #1110 [0].
[0] https://github.com/spring-projects/spring-boot/issues/1110
Issue: SPR-12710
(cherry picked from commit 67934a22e2f77449dc1fd8e614028e3d42e20e81)
Spring Framework 4.0 introduced support for using test-related
annotations as meta-annotations in the Spring TestContext Framework
(TCF) in order to create custom composed annotations within a test
suite; however, the detection of default @Configuration classes in test
classes was not updated to search for @Configuration declared as a
meta-annotation. Specifically, AnnotationConfigContextLoaderUtils
invokes Class.isAnnotated() which only searches for annotations
declared directly on the class in question.
This commit addresses this issue by refactoring the
isDefaultConfigurationClassCandidate() method in
AnnotationConfigContextLoaderUtils so that it uses
AnnotationUtils.findAnnotation() instead of Class.isAnnotated() for
detecting the presence of the @Configuration annotation, either
directly or as a meta-annotation.
Issue: SPR-12659
(cherry picked from commit 2d918380f0553238087ec264688ecba066e49ab5)
In order to allow DefaultActiveProfilesResolver to be reused (e.g., via
extension or delegation), the check which asserts that the 'resolver'
attribute of @ActiveProfiles is not set to a customer resolver class
has been removed.
Issue: SPR-12611
(cherry picked from commit 276712dcd1eef93e2a9add83e3d11f0eb6f06095)
JUnit 4.9 introduced a regression in BlockJUnit4ClassRunner.runChild()
such that exceptions thrown from methodBlock() cause the current test
execution to abort immediately. As a result, the failing test method is
unrooted, and subsequent test methods are never invoked. Furthermore,
RunListeners registered with JUnit are not properly notified.
In conjunction with SPR-11908, SpringJUnit4ClassRunner was updated to
use the aforementioned changes to BlockJUnit4ClassRunner.runChild().
Consequently, SpringJUnit4ClassRunner now suffers from the same
regression.
This commit addresses this issue by ensuring that any exceptions thrown
during the invocation of methodBlock() are properly wrapped in a JUnit
Fail Statement.
Issue: SPR-12613
(cherry picked from commit b81c522ee1624f3d5f170fc3468f4600956950bd)
Prior to this commit, finding out how many application contexts had
been loaded within a test suite required the use of reflection and a
bit of hacking.
This commit addresses this issue by logging ContextCache statistics
whenever an application context is loaded by the Spring TestContext
Framework (TCF).
The log output can be enabled by setting the
"org.springframework.test.context.cache" logging category to DEBUG.
Issue: SPR-12409
Prior to this commit, the getter methods in MockServletContext threw an
UnsupportedOperationException when trying to retrieve Servlet and
Filter registrations.
This commit improves the behavior of these methods by returning null
when a single registration is requested and an empty map when all
registrations are requested. This is now in line with the Javadoc for
ServletContext. Note, however, that the corresponding setter methods
still throw UnsupportedOperationExceptions which is suitable behavior
for a mock.
Issue: SPR-12290
Prior to this commit, AssertThrows in the spring-test module only
supported Exception; however, there are legitimate test cases where the
subject under test (SUT) may potentially throw a subclass of Throwable.
This commit refactors AssertThrows so that it supports exceptions of
type Throwable instead of the limiting support for Exception.
Furthermore, AssertThrows has been refactored to use generics (e.g.,
Class<? extends Throwable> instead of merely Class).
Issue: SPR-6362
Prior to this commit the implementation of isSecure() in
MockHttpServletRequest simply returned the value of the 'secure'
boolean flag. Thus setting the scheme to 'https' had no effect on the
value returned by isSecure() even though most non-mock implementations
(e.g., Tomcat, Jetty, etc.) base the return value on the actual scheme
in the request.
This commit makes the behavior of MockHttpServletRequest.isSecure()
more intuitive by honoring both the 'secure' boolean flag and the
current value of the scheme.
Issue: SPR-12098
Prior to this commit, it was unclear that it was possible to register
custom MIME types when using MockServletContext.
This commit updates the Javadoc for MockServletContext.getMimeType()
with an example of how to achieve this using the MimetypesFileTypeMap
from the Java Activation Framework.
Issue: SPR-12126
Prior to this commit, the getServerName() and getServerPort() methods
in MockHttpServletRequest simply returned the 'mocked' serverName and
serverPort but ignored the 'Host' header entirely. Per the Servlet
specification, however, these methods must parse the server name or
port from the 'Host' header if it is present and otherwise fall back to
the resolved server name or port.
This commit fixes this by ensuring that getServerName() and
getServerPort() properly parse the server's name or port from the
'Host' header if it is present in the request. If the 'Host' header is
not present, MockHttpServletRequest falls back to returning the
'mocked' serverName and serverPort.
Issue: SPR-12088
Prior to this commit, if a custom TestExecutionListener was registered
via @TestExecutionListeners the defaults would not be registered. Thus,
if a user wanted to declare a custom listener and use the default
listeners, the user was forced to manually declare all default
listeners in addition to any custom listeners. This unfortunately
required that the user know exactly which listeners were registered by
default. Moreover, the set of default listeners can change from release
to release, and with the support for automatic discovery of default
listeners introduced in SPR-11466 it is no longer even possible to know
what the set of default TestExecutionListeners is before runtime.
This commit addresses this issue by introducing a mechanism for merging
custom declared listeners with the defaults for the current
environment. Specifically, @TestExecutionListeners supports a new
MergeMode that is used to control whether or not explicitly declared
listeners are merged with the default listeners when
@TestExecutionListeners is declared on a class that does not inherit
listeners from a superclass.
Issue: SPR-8854
Prior to this commit, there was no declarative mechanism for a custom
TestExecutionListener to be registered as a default
TestExecutionListener.
This commit introduces support for discovering default
TestExecutionListener implementations via the SpringFactoriesLoader
mechanism. Specifically, the spring-test module declares all core
default TestExecutionListeners under the
org.springframework.test.context.TestExecutionListener key in its
META-INF/spring.factories properties file, and third-party frameworks
and developers can contribute to the list of default
TestExecutionListeners in the same manner.
- AbstractTestContextBootstrapper uses the SpringFactoriesLoader to
look up the class names of all registered default
TestExecutionListeners and sorts the instantiated listeners using
AnnotationAwareOrderComparator.
- DefaultTestContextBootstrapper and WebTestContextBootstrapper now
rely on the SpringFactoriesLoader mechanism for finding default
TestExecutionListeners instead of hard coding fully qualified class
names.
- To ensure that default TestExecutionListeners are registered in the
correct order, each can implement Ordered or declare @Order.
- AbstractTestExecutionListener and all default TestExecutionListeners
provided by Spring now implement Ordered with appropriate values.
- Introduced "copy constructors" in MergedContextConfiguration and
WebMergedContextConfiguration
- SpringFactoriesLoader now uses AnnotationAwareOrderComparator
instead of OrderComparator.
Issue: SPR-11466
Prior to this commit, if both locations and classes were declared via
@ContextConfiguration at differing levels in a test class hierarchy,
the exception message stated that neither of the default context
loaders was able to load an ApplicationContext from the merged context
configuration, but the message didn't explain why.
This commit adds an explicit check for such scenarios and provides a
more informative exception message similar to the following:
"Neither X nor Y supports loading an ApplicationContext from
[MergedContextConfiguration ...]: declare either 'locations' or
'classes' but not both."
Issue: SPR-12060