Prior to this commit, SQL script annotations and related classes in the
TestContext framework (TCF) were named DatabaseInitializer*. However,
these annotations are not used only for initialization and are
therefore misleading when used for cleaning up the database.
This commit refines the names of annotations and related classes for
configuring SQL scripts to be executed for integration tests in the TCF
as follows:
- @DatabaseInitializer -> @Sql
- @DatabaseInitializers -> @SqlGroup
- DatabaseInitializerTestExecutionListener -> SqlScriptsTestExecutionListener
A special thanks goes out to the following attendees of the Zurich
Hackergarten meeting last night for their collective brainstorming:
@aalmiray, @atsticks, @ollin, @simkuenzi, @tangresh, @vyazelenko.
Issue: SPR-7655
Prior to this commit, it was possible to execute SQL scripts
programmatically via ResourceDatabasePopulator, JdbcTestUtils, and
ScriptUtils. Furthermore, it was also possible to execute SQL scripts
declaratively via the <jdbc> XML namespace. However, it was not
possible to execute SQL scripts declaratively on a per test class or
per test method basis.
This commit makes it possible to declaratively configure SQL scripts
for execution in integration tests via annotations that can be declared
at the class or method level. Details follow.
- Introduced a repeatable @DatabaseInitializer annotation that can be
used to configure SQL scripts at the class or method level with
method-level overrides. @DatabaseInitializers serves as a container
for @DatabaseInitializer.
- Introduced a new DatabaseInitializerTestExecutionListener that is
responsible for parsing @DatabaseInitializer and
@DatabaseInitializers and executing SQL scripts.
- DatabaseInitializerTestExecutionListener is registered by default in
abstract base test classes as well as in TestContextBootstrapper
implementations.
- @DatabaseInitializer and @DatabaseInitializers may be used as
meta-annotations; however, attribute overrides are not currently
supported for repeatable annotations used as meta-annotations. This
is a known limitation of Spring's AnnotationUtils.
- The semantics for locating SQL script resources is consistent with
@ContextConfiguration's semantics for locating XML configuration
files. In addition, a default SQL script can be detected based
either on the name of the annotated class or on the name of the
annotated test method.
- @DatabaseInitializer allows for specifying which DataSource and
PlatformTransactionManager to use from the test's
ApplicationContext, including default conventions consistent with
TransactionalTestExecutionListener and @TransactionConfiguration.
- @DatabaseInitializer supports all of the script configuration options
currently supported by ResourceDatabasePopulator.
- @DatabaseInitializer and DatabaseInitializerTestExecutionListener
support execution phases for scripts that dictate when SQL scripts
are executed (i.e., before or after a test method).
- SQL scripts can be executed within the current test's transaction if
present, outside of the current test's transaction if present, or
always in a new transaction, depending on the value of the boolean
requireNewTransaction flag in @DatabaseInitializer.
- DatabaseInitializerTestExecutionListener delegates to
ResourceDatabasePopulator#execute to actually execute the scripts.
Issue: SPR-7655
This commit upgrades Hibernate-based integration tests in the
spring-test module to use Hibernate 4 instead of 3 and Hibernate
Validator 5 instead of 4. This streamlines and simplifies our
dependency management at the same time.
Issue: SPR-11834
Work done in conjunction with SPR-5243 and SPR-4588 introduced physical
package cycles in the spring-test module. The work performed in
conjunction with SPR-9924 uses reflection to resolve these physical
package cycles; however, prior to this commit the logical package
cycles still remain.
Furthermore, over time it has become apparent that the Spring
TestContext Framework (TCF) could better serve application developers
and especially third-party framework developers by providing a more
flexible mechanism for "bootstrapping" the TCF. For example, prior to
this commit, default TestExecutionListeners could only be registered by
subclassing TestContextManager (and SpringJUnit4ClassRunner if using
JUnit). Similarly, the default ContextLoader could only be set by
subclassing SpringJUnit4ClassRunner for JUnit and by copying and
modifying AbstractTestNGSpringContextTests for TestNG.
This commit addresses the aforementioned issues by introducing a
bootstrap strategy in the TestContext framework that is responsible for
determining default TestExecutionListeners and the default
ContextLoader in an extensible fashion. The new TestContextBootstrapper
SPI also provides a mechanism for supporting various types of
MergedContextConfiguration depending on the feature set of the context
loaders supported by the strategy.
The following provides an overview of the most significant changes in
this commit.
- Introduced TestContextBootstrapper strategy SPI, BootstrapContext,
and @BootstrapWith.
- Introduced AbstractTestContextBootstrapper,
DefaultTestContextBootstrapper, and WebTestContextBootstrapper
implementations of the TestContextBootstrapper SPI and extracted
related reflection code from ContextLoaderUtils & TestContextManager.
- Introduced BootstrapUtils for retrieving the TestContextBootstrapper
from @BootstrapWith, falling back to a default if @BootstrapWith is
not present.
- @WebAppConfiguration is now annotated with
@BootstrapWith(WebTestContextBootstrapper.class).
- CacheAwareContextLoaderDelegate is now an interface with a new
DefaultCacheAwareContextLoaderDelegate implementation class.
- Introduced closeContext(MergedContextConfiguration, HierarchyMode) in
CacheAwareContextLoaderDelegate.
- DefaultTestContext now uses CacheAwareContextLoaderDelegate instead
of interacting directly with the ContextCache.
- DefaultTestContext now delegates to a TestContextBootstrapper for
building the MergedContextConfiguration.
- TestContextManager now delegates to TestContextBootstrapper for
retrieving TestExecutionListeners.
- Deleted TestContextManager(Class, String) constructor and
SpringJUnit4ClassRunner.getDefaultContextLoaderClassName(Class)
method since default ContextLoader support is now implemented by
TestContextBootstrappers.
- Extracted ActiveProfilesUtils from ContextLoaderUtils.
- Extracted ApplicationContextInitializerUtils from ContextLoaderUtils.
- MetaAnnotationUtils is now a public utility class in the test.util
package.
- Removed restriction in @ActiveProfiles that a custom resolver cannot
be used with the 'value' or 'profiles' attributes.
- Introduced DefaultActiveProfilesResolver.
Issue: SPR-9955
This commit introduces an explicit integration test to verify that a
PropertySource can be set via a custom ApplicationContextInitializer in
the Spring TestContext Framework.
Issue: SPR-11666
Prior to this commit, the Spring TestContext Framework did not support
the declaration of both 'locations' and 'classes' within
@ContextConfiguration at the same time.
This commit addresses this in the following manner:
- ContextConfigurationAttributes no longer throws an
IllegalArgumentException if both 'locations' and 'classes' are
supplied to its constructor.
- Concrete SmartContextLoader implementations now validate the
supplied MergedContextConfiguration before attempting to load the
ApplicationContext. See validateMergedContextConfiguration().
- Introduced tests for hybrid context loaders like the one used in
Spring Boot. See HybridContextLoaderTests.
- Updated the Testing chapter of the reference manual so that it no
longer states that locations and classes cannot be used
simultaneously, mentioning Spring Boot as well.
- The Javadoc for @ContextConfiguration has been updated accordingly.
- Added hasLocations(), hasClasses(), and hasResources() convenience
methods to MergedContextConfiguration.
Issue: SPR-11634
To simplify common use cases, this commit introduces a new
execute(DataSource) method in ResourceDatabasePopulator that complements
the existing populate(Connection) method.
Issue: SPR-11629
Prior to this commit, if multiple test methods were executed in a
subclass of AbstractTestNGSpringContextTests annotated with
@WebAppConfiguration, then injected Servlet API mocks would only
reference the mocks created for the first test method. Subsequent test
methods could therefore never reference the current mocks, and there
was a discrepancy between the state of the injected mocks and the mock
set in the RequestContextHolder.
This commit addresses this issue by ensuring that dependencies
(including updated mocks) are injected into the test instance before
the next test method if the ServletTestExecutionListener resets the
request attributes in RequestContextHolder.
Issue: SPR-11626
This commit adds new MockHttpServletRequestBuilder constructors
with an URI parameter in addition to the URL template + URL variables
existing ones.
It gives more control on how the URL is built, allowing for example to
use URL variables containing '/' character with proper encoding.
Issue: SPR-11441
Prior to this commit, the codebase was using a mix of log4j.xml
and log4j.properties for test-related logging configuration. This
can be an issue as log4j takes the xml variant first when looking
for a default bootstrap configuration.
In practice, some modules declaring the properties variant were
taking the xml variant configuration from another module.
The general structure of the configuration has also been
harmonized to provide a standard console output as well as an
easy way to enable trace logs for the current module.
This commit continues the work in the previous commit as follows:
- Introduced an exception hierarchy for exceptions related to SQL
scripts, with ScriptException as the base.
- CannotReadScriptException and ScriptStatementFailedException now
extend ScriptException.
- Introduced ScriptParseException, used by ScriptUtils.splitSqlScript().
- DatabasePopulatorUtils.execute() now explicitly throws a
DataAccessException.
- Polished Javadoc in ResourceDatabasePopulator.
- Overhauled Javadoc in ScriptUtils and documented all constants.
- Added missing @author tags for original authors in ScriptUtils and
ScriptUtilsTests.
- ScriptUtils.splitSqlScript() now asserts preconditions.
- Deleted superfluous methods in ScriptUtils and changed method
visibility to private or package private as appropriate.
- Deleted the ScriptStatementExecutor introduced in the previous
commit; ScriptUtils.executeSqlScript() now accepts a JDBC Connection;
JdbcTestUtils, AbstractTransactionalJUnit4SpringContextTests, and
AbstractTransactionalTestNGSpringContextTests now use
DatabasePopulatorUtils to execute a ResourceDatabasePopulator instead
of executing a script directly via ScriptUtils.
- Introduced JdbcTestUtilsIntegrationTests.
Issue: SPR-9531
Prior to this commit neither ResourceDatabasePopulator nor
JdbcTestUtils properly supported multi-line comments (e.g., /* ... */).
Secondarily there has developed a significant amount of code
duplication in these two classes that has led to maintenance issues
over the years.
This commit addresses these issues as follows:
- Common code has been extracted from ResourceDatabasePopulator and
JdbcTestUtils and moved to a new ScriptUtils class in the
spring-jdbc module.
- Relevant test cases have been migrated from JdbcTestUtilsTests to
ScriptUtilsTests.
- ScriptUtils.splitSqlScript() has been modified to ignore multi-line
comments in scripts during processing.
- ResourceDatabasePopulator supports configuration of the start and end
delimiters for multi-line (block) comments.
- A new test case was added to ScriptUtilsTests for the new multi-line
comment support.
Issue: SPR-9531
This commit aligns our include and exclude filters for test classes
with Gradle's standard patterns. Specifically, our patterns now end
with ".class" instead of ".*".
The aforementioned change makes the exclusion of inner classes
unnecessary. Thus, patterns for test classes ending with "TestCase" or
"TestSuite" have been deleted.
Furthermore, the include and exclude patterns previously used in the
spring-test module made it impossible for the
FailingBeforeAndAfterMethodsTests class in the 'testng' package to ever
be executed by the build. This has been addressed by renaming our JUnit
and TestNG variants of FailingBeforeAndAfterMethodsTests and moving the
TestNG variant into the 'junit' package so that it can be picked with
our standard include pattern for JUnit-based tests.
This change removes the use of a CountDownLatch to wait for the
asynchronously computed controller method return value. Instead we
check in a loop every 200 milliseconds if the result has been set.
If the result is not set within the specified amount of time to wait
an IllegalStateException is raised.
Additional changes:
- Use AtomicReference to hold the async result
- Remove @Ignore annotations on AsyncTests methods
- Remove checks for the presence of Servlet 3
Issue: SPR-11516
This commit introduces a new isInJavaLangAnnotationPackage(Annotation)
method in AnnotationUtils. This method is now used in AnnotationUtils,
AnnotatedElementUtils, and MetaAnnotationUtils to ensure that search
algorithms do no search for meta-annotations on annotations in the
"java.lang.annotation" package.
The following are some empirical results from this change:
- The number of times that the findAnnotation(Class,Class,Set) method in
AnnotationUtils is recursively invoked while executing
AnnotationUtilsTests drops from 51 to 29.
- The number of times that the process(AnnotatedElement) method in
AnnotationUtils.AnnotationCollector is recursively invoked while
executing AnnotationUtilsTests.getRepeatableFromMethod() drops
from 16 to 2.
- The number of times that the doProcess() method in
AnnotatedElementUtils is recursively invoked while executing the
"getAnnotationAttributes() On MetaCycleAnnotatedClass with missing
target meta-annotation" test in AnnotatedElementUtilsTests drops
from 23 to 5.
- The number of times that the findAnnotationDescriptor(Class,Set,Class)
method in MetaAnnotationUtils is recursively invoked while executing
the "findAnnotationDescriptor() on MetaCycleAnnotatedClass with
missing target meta-annotation" test in MetaAnnotationUtilsTests drops
from 16 to 8.
Issue: SPR-11483