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
Prior to this commit, the following methods in ContextLoaderUtils
treated a composed @ContextConfiguration annotation (i.e., a custom
annotation that is meta-annotated with @ContextConfiguration) as the
"declaring class" instead of the actual test class.
- resolveContextConfigurationAttributes()
- resolveContextHierarchyAttributes()
As a consequence, if @ContextConfiguration is used as a
meta-annotation, the meta-annotated class is stored as the
"declaringClass" in ContextConfigurationAttributes. Thus, when a
ContextLoader (or SmartContextLoader) attempts to detect default
resource locations or configuration classes, it does so for the
composed annotation class instead of for the declaring test class.
This commit ensures that ContextLoaders are supplied the declaring test
class instead of the composed annotation class in such use cases.
Issue: SPR-11455
Prior to this commit, the findAnnotationDescriptor() and
findAnnotationDescriptorForTypes() methods in MetaAnnotationUtils only
supported a single level of meta-annotations. In particular, this kept
the following annotations from being used as meta-annotations on
meta-annotations:
- @ContextConfiguration
- @ContextHierarchy
- @ActiveProfiles
- @TestExecutionListeners
This commit alters the search algorithms used in MetaAnnotationUtils so
that arbitrary levels of meta-annotations are now supported for the
aforementioned test-related annotations.
Issue: SPR-11470
Prior to this commit, if @ActiveProfiles were used as a meta-annotation
on a composed annotation, then the composed annotation's class would be
passed to the ActiveProfilesResolver.resolve() method instead of the
test class, which breaks the contract for ActiveProfilesResolver.
This commit addresses this issue by ensuring that the actual test class
is always passed to ActiveProfilesResolver.resolve().
Issue: SPR-11467
mimeType is not a valid method on ContentResultMatche.
I have signed and agree to the terms of the SpringSource Individual
Contributor License Agreement.
- Consistent importing of org.junit.Assert.*;
- Proper declaration of expected exceptions via @Test(expected).
- Renamed SpEL ExpressionTestCase to AbstractExpressionTests.
- Formatting and test method naming conventions.
Prior to this commit several test classes named "*Test" were not
recognized as tests by the Gradle build. This is due to the configured
inclusion of '**/*Tests.*' which follows Spring's naming convention for
test classes.
This commit addresses this issue by:
- Renaming real test classes consistently to "*Tests".
- Renaming internal test classes to "*TestCase".
- Renaming @WebTest to @WebTestStereotype.
- Disabling broken tests in AnnoDrivenStaticEntityMockingControlTest.
- Modifying the Gradle build configuration so that classes ending in
either "*Tests" or "*Test" are considered test classes.
Issue: SPR-11384
SPR-11145 claims that ServletContextAware beans declared in an
ApplicationContext loaded for an integration test by the TestContext
framework (TCF) do not have their setServletContext() methods invoked
if the tests are executed manually using JUnit 4.11.
This commit verifies that such ServletContextAware beans are processed
properly regardless of how the test was launched. Specifically:
- A ServletContextAwareBean has been introduced.
- BasicAnnotationConfigWacTests has been retrofitted with a
ServletContextAwareBean in its context.
- ServletContextAwareBeanWacTests has been introduced to execute
BasicAnnotationConfigWacTests manually via JUnitCore.
Issue: SPR-11145
equalTo is not a valid method on JsonPathResultMatchers
I have signed and agree to the terms of the SpringSource Individual Contributor License Agreement.
Prior to this commit, a NoClassDefFoundError caught in
TestContextManager's retrieveTestExecutionListeners() method would be
handled differently for implicit default listeners (i.e., listeners not
declared via @TestExecutionListeners) and listeners explicitly declared
via @TestExecutionListeners. Specifically, a NoClassDefFoundError would
cause a test to fail for an explicitly declared TestExecutionListener
but not for an implicitly declared one.
This commit addresses this issue by:
- Always swallowing a NoClassDefFoundError for both implicitly and
explicitly declared TestExecutionListeners.
- Changing the log level from DEBUG to INFO to make such situations
more visible to the average end user.
Issue: SPR-11347
This commit deletes methods in RollbackForRequiredEjbTxDaoTestNGTests
that were unnecessarily redeclared. The redeclaration is required for
JUnit's @FixMethodOrder support but not for TestNG's built-in support
for dependent methods.
Issue: SPR-6132
This commit introduces transactional integration tests executing
against both JUnit and TestNG in the TestContext framework (TCF) using
@TransactionAttribute in EJBs instead of Spring’s @Transactional
annotation.
These tests disprove the claims raised in SPR-6132 by demonstrating that
transaction support in the TCF works as expected when a transactional
EJB method that is configured with TransactionAttribute.REQUIRES_NEW is
invoked. Specifically:
- The transaction managed by the TCF is suspended while such an EJB
method is invoked.
- Any work performed within the new transaction for the EJB method is
committed after the method invocation completes.
- The transaction managed by the TCF is resumed and subsequently
either rolled back or committed as necessary based on the
configuration of @Rollback and @TransactionConfiguration.
The configuration for the JUnit-based tests is straightforward and self
explanatory; however, the configuration for the TestNG tests is less
intuitive.
In order for the TCF to function properly, the developer must ensure
that test methods within a given TestNG test (whether defined locally,
in a superclass, or somewhere else in the suite) are executed in the
proper order. In a stand-alone test class this is straightforward;
however, in a test class hierarchy (or test suite) with dependent
methods, it is necessary to configure TestNG so that all methods within
an individual test are executed in isolation from test methods in other
tests. This can be achieved by configuring a test class to run in its
own uniquely identified suite (e.g., by annotating each concrete
TestNG-based test class with @Test(suiteName = "< Some Unique Suite
Name >")).
For example, without specifying a unique suite name for the TestNG
tests introduced in this commit, test methods will be executed in the
following (incorrect) order:
- CommitForRequiredEjbTxDaoTestNGTests.test1InitialState()
- CommitForRequiresNewEjbTxDaoTestNGTests.test1InitialState()
- RollbackForRequiresNewEjbTxDaoTestNGTests.test1InitialState()
- RollbackForRequiredEjbTxDaoTestNGTests.test1InitialState()
- CommitForRequiredEjbTxDaoTestNGTests.test2IncrementCount1()
The reason for this ordering is that test2IncrementCount1() depends on
test1InitialState(); however, the intention of the developer is that
the tests for an individual test class are independent of those in
other test classes. So by specifying unique suite names for each test
class, the following (correct) ordering is achieved:
- RollbackForRequiresNewEjbTxDaoTestNGTests.test1InitialState()
- RollbackForRequiresNewEjbTxDaoTestNGTests.test2IncrementCount1()
- RollbackForRequiresNewEjbTxDaoTestNGTests.test3IncrementCount2()
- CommitForRequiredEjbTxDaoTestNGTests.test1InitialState()
- CommitForRequiredEjbTxDaoTestNGTests.test2IncrementCount1()
- CommitForRequiredEjbTxDaoTestNGTests.test3IncrementCount2()
- RollbackForRequiredEjbTxDaoTestNGTests.test1InitialState()
- RollbackForRequiredEjbTxDaoTestNGTests.test2IncrementCount1()
- RollbackForRequiredEjbTxDaoTestNGTests.test3IncrementCount2()
- CommitForRequiresNewEjbTxDaoTestNGTests.test1InitialState()
- CommitForRequiresNewEjbTxDaoTestNGTests.test2IncrementCount1()
- CommitForRequiresNewEjbTxDaoTestNGTests.test3IncrementCount2()
See the JIRA issue for more detailed log output.
Furthermore, @DirtiesContext(classMode = ClassMode.AFTER_CLASS) has
been used in both the JUnit and TestNG tests introduced in this commit
in order to ensure that the in-memory database is reinitialized between
each test class.
Issue: SPR-6132
The ServletTestExecutionListener is now prepended to the set of default
listeners in AbstractJUnit4SpringContextTests and
AbstractTestNGSpringContextTests.
Issue: SPR-11340