The changes made in 0cb22fc8f3 would
result in contexts not being properly closed if evicted from the
ConcurrentReferenceHashMap by the Garbage Collector.
This commit reverts those changes and returns to using standard
ConcurrentHashMaps for the time being.
Issue: SPR-7687
- DefaultBootstrapContext and DefaultCacheAwareContextLoaderDelegate
are now public classes in the 'support' subpackage.
- Introduced getCacheAwareContextLoaderDelegate() in
AbstractTestContextBootstrapper as an extension point for configuring
custom ContextCache support.
- Introduced reflection-based createBootstrapContext() utility method
in BootstrapUtils; TestContextManager now delegates to BootstrapUtils
in order to avoid package cycles.
- Introduced logStatistics() method in the ContextCache API and defined
statistics logging category as a constant.
- DefaultCacheAwareContextLoaderDelegate now delegates to
ContextCache.logStatistics().
Issue: SPR-12683
This commit moves the responsibility of building a TestContext from the
TestContextManager to a TestContextBootstrapper.
In addition, DefaultTestContext is now a public class residing in the
"support" subpackage.
Issue: SPR-12683
Prior to this commit, the ContextCache in the Spring TestContext
Framework (TCF) cached ApplicationContexts in a ConcurrentHashMap using
strong references. This practice can occasionally lead to
OutOfMemoryErrors when running a large number of tests in a test suite
with varying context configuration since the context cache becomes
overpopulated over time.
This commit addresses this issue by using Spring's
ConcurrentReferenceHashMap which uses SoftReferences for both the keys
(i.e., MergedContextConfiguration instances) and values (i.e.,
ApplicationContexts) stored in the map that backs the ContextCache.
Issue: SPR-7687
Prior to this commit, ClassLevelDirtiesContextTests existed for
verifying the expected behavior of @DirtiesContext declared at the
class level in conjunction with JUnit and SpringJUnit4ClassRunner.
This commit introduces analogous tests for TestNG in the new
ClassLevelDirtiesContextTestNGTests class.
Furthermore, ContextCacheTestUtils and TrackingTestNGTestListener have
been introduced to reduce code duplication across the test suite.
Issue: SPR-12918
This commit increases the extensibility of
AbstractTestContextBootstrapper by making the resolveContextLoader()
and resolveExplicitContextLoaderClass() methods protected instead of
private.
Furthermore, resolveContextLoader() now throws an IllegalStateException
if getDefaultContextLoaderClass() returns null.
Issue: SPR-12682
Prior to this commit it was possible to set or get a static field using
ReflectionTestUtils but only if an instance of the target class was
available.
This commit introduces dedicated support for setting and getting static
fields in ReflectionTestUtils when only the target class is available.
Furthermore, this commit increases the robustness of
ReflectionTestUtilsTests regarding expected exceptions and simplifies
the Javadoc for ReflectionTestUtils.
Issue: SPR-6792
Since SPR-11792, Last-Modified and ETag headers are also written in
`HTTP 304 Not Modified` responses. This is expected as per
https://tools.ietf.org/html/rfc7232#section-4.1 .
Those tests expected "Last-Modified" to be missing in case of HTTP 304
responses, which is not the case anymore since 953608ec .
Issue: SPR-11792
Prior to this commit, @DirtiesContext could only be used to close a
test ApplicationContext after an entire test class or after a test
method; however, there are some use cases for which it would be
beneficial to close a test ApplicationContext before a given test class
or test method -- for example, if some rogue (i.e., yet to be
determined) test within a large test suite has corrupted the original
configuration for the ApplicationContext.
This commit provides a solution to such testing challenges by
introducing the following modes for @DirtiesContext.
- MethodMode.BEFORE_METHOD: configured via the new methodMode attribute
- ClassMode.BEFORE_CLASS and ClassMode.BEFORE_EACH_TEST_METHOD: both
configured via the existing classMode attribute
Issue: SPR-12429
This commit updates the Spr8849Tests test suite to include XML
configuration that guarantees that a unique database name is always
automatically generated (via the new 'generate-name' attribute that was
introduced in SPR-8849) while reusing the same bean name (i.e.,
'dataSource').
Issue: SPR-8849
This commit refactors the XML configuration used by the tests in the
Spr8849Tests test suite so that a unique database name is always
generated (via the new 'database-name' attribute that was introduced in
SPR-12835) while reusing the same bean name (i.e., 'dataSource').
This is a much more robust alternative to the previous work-around
since the name of the DataSource does not randomly change across
application contexts, thus allowing proper autowiring by name and bean
referencing within XML configuration.
Issue: SPR-8849
This commit simplifies the implementations of loadBeanDefinitions() in
GenericGroovyXmlContextLoader and GenericGroovyXmlWebContextLoader.
Due to the recent bug fix for GroovyBeanDefinitionReader regarding full
support for XML config files, these Groovy context loaders can now
simply use a GroovyBeanDefinitionReader instead of a
GroovyBeanDefinitionReader plus an XmlBeanDefinitionReader.
Issue: SPR-12769
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
- 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
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
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
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
Add support for annotation-based event listeners. Enabled automatically
when using Java configuration or can be enabled explicitly via the
regular <context:annotation-driven/> XML element. Detect methods of
managed beans annotated with @EventListener, either directly or through
a meta-annotation.
Annotated methods must define the event type they listen to as a single
parameter argument. Events are automatically filtered out according to
the method signature. When additional runtime filtering is required, one
can specify the `condition` attribute of the annotation that defines a
SpEL expression that should match to actually invoke the method for a
particular event. The root context exposes the actual `event`
(`#root.event`) and method arguments (`#root.args`). Individual method
arguments are also exposed via either the `a` or `p` alias (`#a0` refers
to the first method argument). Finally, methods arguments are exposed via
their names if that information can be discovered.
Events can be either an ApplicationEvent or any arbitrary payload. Such
payload is wrapped automatically in a PayloadApplicationEvent and managed
explicitly internally. As a result, users can now publish and listen
for arbitrary objects.
If an annotated method has a return value, an non null result is actually
published as a new event, something like:
@EventListener
public FooEvent handle(BarEvent event) { ... }
Events can be handled in an aynchronous manner by adding `@Async` to the
event method declaration and enabling such infrastructure. Events can
also be ordered by adding an `@Order` annotation to the event method.
Issue: SPR-11622
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
Various parts of the reference manual as well as the Javadoc for
AnnotationConfigContextLoaderUtils improperly refer to "static inner
classes" even though this terminology does not exist in Java. The Java
Language Specification explicitly refers to such classes as "static
nested classes." An "inner class" must be non-static by definition.
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
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
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
Spring Framework 3.1 introduced an Environment abstraction with support
for hierarchical PropertySources that can be configured
programmatically as well as declaratively via the @PropertySource
annotation. However, prior to this commit, there was no way to
declaratively configure PropertySources in integration tests in the
Spring TestContext Framework (TCF).
This commit introduces declarative support for PropertySources in the
TCF via a new class-level @TestPropertySource annotation. This
annotation provides two options for declaring test property sources:
- The 'locations' attribute allows developers to declare external
resource locations for test properties files.
- The 'properties' attribute allows developers to declare inlined
properties in the form of key-value pairs.
Test properties files are added to the Environment before all other
property sources and can therefore override system and application
property sources. Similarly, inlined properties are added to the
Environment before all other property sources and can therefore
override system property sources, application property sources, and
test properties files.
Specifically, this commit introduces the following major changes:
- Introduced @TestPropertySource annotation along with internal
TestPropertySourceAttributes, MergedTestPropertySources, and
TestPropertySourceUtils for working with test property sources
within the TCF.
- All TestContextBootstrappers have been modified to support the
merged property resource locations and inlined properties from
@TestPropertySource.
- MergedContextConfiguration (and consequently the context caching
key) is now additionally based on the merged property resource
locations and inlined properties from @TestPropertySource. The same
applies to WebMergedContextConfiguration.
- AbstractContextLoader's prepareContext() method now adds
PropertySources for all resource locations and inlined properties
from the supplied MergedContextConfiguration to the Environment of
the supplied ApplicationContext. All subclasses of
AbstractGenericContextLoader and AbstractGenericWebContextLoader
therefore automatically provide support for @TestPropertySource.
Issue: SPR-12051
Replace references to the old RFC 2616 (HTTP 1.1) with references
to the new RFCs 7230 to 7235.
This commit also deprecates:
- HttpStatus.USE_PROXY
- HttpStatus.REQUEST_ENTITY_TOO_LARGE in favor of HttpStatus.PAYLOAD_TOO_LARGE
- HttpStatus.REQUEST_URI_TOO_LONG in favor of HttpStatus.URI_TOO_LONG
Issue: SPR-12067
Surprisingly until now the MockMvcRequestBuilders did not have methods
for HTTP HEAD. This change adds such methods to the API making it
consistent with other HTTP method types.
Issue: SPR-12055
This commit updates the Javadoc for getLocale() and getLocales() in
MockHttpServletRequest to point out that the mock implementation does
not comply with the the Servlet specification with regard to the
Accept-Language header.
Issue: SPR-12043