public class TransactionalTestExecutionListener extends AbstractTestExecutionListener
TestExecutionListener
that provides support for executing tests
within test-managed transactions by honoring Spring's
@Transactional
annotation.
Test-managed transactions are transactions that are managed
declaratively via this listener or programmatically via
TestTransaction
. Such transactions should not be confused with
Spring-managed transactions (i.e., those managed directly
by Spring within the ApplicationContext
loaded for tests) or
application-managed transactions (i.e., those managed
programmatically within application code that is invoked via tests).
Spring-managed and application-managed transactions will typically
participate in test-managed transactions; however, caution should be
taken if Spring-managed or application-managed transactions are
configured with any propagation type other than
REQUIRED
or SUPPORTS
.
Annotating a test method with @Transactional
causes the test
to be run within a transaction that will, by default, be automatically
rolled back after completion of the test. If a test class is
annotated with @Transactional
, each test method within that class
hierarchy will be run within a transaction. Test methods that are
not annotated with @Transactional
(at the class or method
level) will not be run within a transaction. Furthermore, tests that
are annotated with @Transactional
but have the
propagation
type set to
NOT_SUPPORTED
will not be run within a transaction.
By default, test transactions will be automatically rolled back
after completion of the test; however, transactional commit and rollback
behavior can be configured declaratively via the class-level
@TransactionConfiguration
and method-level
@Rollback
annotations.
As of Spring Framework 4.1, it is possible to interact with test-managed
transactions programmatically via the static methods in TestTransaction
.
TestTransaction
may be used within test methods,
before methods, and after methods.
When executing transactional tests, it is sometimes useful to be able to
execute certain set up or tear down code outside of a
transaction. TransactionalTestExecutionListener
provides such
support for methods annotated with
@BeforeTransaction
or
@AfterTransaction
.
TransactionalTestExecutionListener
expects a
PlatformTransactionManager
bean to be defined in the Spring
ApplicationContext
for the test. In case there are multiple
instances of PlatformTransactionManager
within the test's
ApplicationContext
, @TransactionConfiguration
supports
configuring the bean name of the PlatformTransactionManager
that
should be used to drive transactions. Alternatively, a qualifier
may be declared via
@Transactional("myQualifier")
, or
TransactionManagementConfigurer
can be implemented by an
@Configuration
class. See TestContextTransactionUtils.retrieveTransactionManager(org.springframework.test.context.TestContext, java.lang.String)
for details on the algorithm used to look up a transaction manager in
the test's ApplicationContext
.
TransactionConfiguration
,
TransactionManagementConfigurer
,
Transactional
,
Rollback
,
BeforeTransaction
,
AfterTransaction
,
TestTransaction
Modifier and Type | Field and Description |
---|---|
protected TransactionAttributeSource |
attributeSource |
private TransactionConfigurationAttributes |
configurationAttributes |
private static TransactionConfiguration |
defaultTransactionConfiguration |
private static Log |
logger |
HIGHEST_PRECEDENCE, LOWEST_PRECEDENCE
Constructor and Description |
---|
TransactionalTestExecutionListener() |
Modifier and Type | Method and Description |
---|---|
void |
afterTestMethod(TestContext testContext)
If a transaction is currently active for the supplied
test context, this method will end the transaction
and run
@AfterTransaction methods. |
void |
beforeTestMethod(TestContext testContext)
If the test method of the supplied test context
is configured to run within a transaction, this method will run
@BeforeTransaction methods and start a new
transaction. |
private java.util.List<java.lang.reflect.Method> |
getAnnotatedMethods(java.lang.Class<?> clazz,
java.lang.Class<? extends java.lang.annotation.Annotation> annotationType)
Gets all methods in the supplied
class and its superclasses
which are annotated with the supplied annotationType but
which are not shadowed by methods overridden in subclasses. |
int |
getOrder()
Returns
4000 . |
private java.util.List<java.lang.Class<?>> |
getSuperClasses(java.lang.Class<?> clazz)
Gets all superclasses of the supplied
class , including the
class itself. |
protected PlatformTransactionManager |
getTransactionManager(TestContext testContext)
Get the
transaction manager to use
for the supplied test context . |
protected PlatformTransactionManager |
getTransactionManager(TestContext testContext,
java.lang.String qualifier)
|
protected boolean |
isDefaultRollback(TestContext testContext)
Determine whether or not to rollback transactions by default for the
supplied
test context . |
protected boolean |
isRollback(TestContext testContext)
Determine whether or not to rollback transactions for the supplied
test context by taking into consideration the
default rollback flag and a
possible method-level override via the Rollback annotation. |
private boolean |
isShadowed(java.lang.reflect.Method method,
java.util.List<java.lang.reflect.Method> previousMethods)
Determine if the supplied
method is shadowed by
a method in the supplied list of previous methods. |
private boolean |
isShadowed(java.lang.reflect.Method current,
java.lang.reflect.Method previous)
Determine if the supplied
current method is shadowed
by a previous method . |
(package private) TransactionConfigurationAttributes |
retrieveConfigurationAttributes(TestContext testContext)
Retrieves the
TransactionConfigurationAttributes for the
specified class which may optionally declare or inherit
@TransactionConfiguration . |
protected void |
runAfterTransactionMethods(TestContext testContext)
Run all
@AfterTransaction methods for the
specified test context . |
protected void |
runBeforeTransactionMethods(TestContext testContext)
Run all
@BeforeTransaction methods for the
specified test context . |
afterTestClass, beforeTestClass, prepareTestInstance
private static final Log logger
private static final TransactionConfiguration defaultTransactionConfiguration
protected final TransactionAttributeSource attributeSource
private TransactionConfigurationAttributes configurationAttributes
public final int getOrder()
4000
.getOrder
in interface Ordered
getOrder
in class AbstractTestExecutionListener
public void beforeTestMethod(TestContext testContext) throws java.lang.Exception
@BeforeTransaction
methods and start a new
transaction.
Note that if a @BeforeTransaction
method fails, any remaining
@BeforeTransaction
methods will not be invoked, and a transaction
will not be started.
beforeTestMethod
in interface TestExecutionListener
beforeTestMethod
in class AbstractTestExecutionListener
testContext
- the test context in which the test method will be
executed; never null
java.lang.Exception
- allows any exception to propagateTransactional
,
getTransactionManager(TestContext, String)
public void afterTestMethod(TestContext testContext) throws java.lang.Exception
@AfterTransaction
methods.
@AfterTransaction
methods are guaranteed to be invoked even if
an error occurs while ending the transaction.
afterTestMethod
in interface TestExecutionListener
afterTestMethod
in class AbstractTestExecutionListener
testContext
- the test context in which the test method was
executed; never null
java.lang.Exception
- allows any exception to propagateprotected void runBeforeTransactionMethods(TestContext testContext) throws java.lang.Exception
@BeforeTransaction
methods for the
specified test context
. If one of the methods fails,
however, the caught exception will be rethrown in a wrapped
RuntimeException
, and the remaining methods will not
be given a chance to execute.testContext
- the current test contextjava.lang.Exception
protected void runAfterTransactionMethods(TestContext testContext) throws java.lang.Exception
@AfterTransaction
methods for the
specified test context
. If one of the methods fails,
the caught exception will be logged as an error, and the remaining
methods will be given a chance to execute. After all methods have
executed, the first caught exception, if any, will be rethrown.testContext
- the current test contextjava.lang.Exception
protected PlatformTransactionManager getTransactionManager(TestContext testContext, java.lang.String qualifier)
transaction manager
to use
for the supplied test context and qualifier
.
Delegates to getTransactionManager(TestContext)
if the
supplied qualifier
is null
or empty.
testContext
- the test context for which the transaction manager
should be retrievedqualifier
- the qualifier for selecting between multiple bean matches;
may be null
or emptynull
if not foundBeansException
- if an error occurs while retrieving the transaction managergetTransactionManager(TestContext)
protected PlatformTransactionManager getTransactionManager(TestContext testContext)
transaction manager
to use
for the supplied test context
.
The default implementation simply delegates to
TestContextTransactionUtils.retrieveTransactionManager(org.springframework.test.context.TestContext, java.lang.String)
.
testContext
- the test context for which the transaction manager
should be retrievednull
if not foundBeansException
- if an error occurs while retrieving an explicitly
named transaction managergetTransactionManager(TestContext, String)
protected final boolean isDefaultRollback(TestContext testContext) throws java.lang.Exception
test context
.testContext
- the test context for which the default rollback flag
should be retrievedjava.lang.Exception
- if an error occurs while determining the default rollback flagprotected final boolean isRollback(TestContext testContext) throws java.lang.Exception
test context
by taking into consideration the
default rollback
flag and a
possible method-level override via the Rollback
annotation.testContext
- the test context for which the rollback flag
should be retrievedjava.lang.Exception
- if an error occurs while determining the rollback flagprivate java.util.List<java.lang.Class<?>> getSuperClasses(java.lang.Class<?> clazz)
class
, including the
class itself. The ordering of the returned list will begin with the
supplied class and continue up the class hierarchy, excluding Object
.
Note: This code has been borrowed from
org.junit.internal.runners.TestClass#getSuperClasses(Class)
and
adapted.
clazz
- the class for which to retrieve the superclassesObject
private java.util.List<java.lang.reflect.Method> getAnnotatedMethods(java.lang.Class<?> clazz, java.lang.Class<? extends java.lang.annotation.Annotation> annotationType)
class
and its superclasses
which are annotated with the supplied annotationType
but
which are not shadowed by methods overridden in subclasses.
Note: This code has been borrowed from
org.junit.internal.runners.TestClass#getAnnotatedMethods(Class)
and adapted.
clazz
- the class for which to retrieve the annotated methodsannotationType
- the annotation type for which to searchprivate boolean isShadowed(java.lang.reflect.Method method, java.util.List<java.lang.reflect.Method> previousMethods)
method
is shadowed by
a method in the supplied list
of previous methods.
Note: This code has been borrowed from
org.junit.internal.runners.TestClass#isShadowed(Method, List)
.
method
- the method to check for shadowingpreviousMethods
- the list of methods which have previously been processedtrue
if the supplied method is shadowed by a
method in the previousMethods
listprivate boolean isShadowed(java.lang.reflect.Method current, java.lang.reflect.Method previous)
current method
is shadowed
by a previous method
.
Note: This code has been borrowed from
org.junit.internal.runners.TestClass#isShadowed(Method, Method)
.
current
- the current methodprevious
- the previous methodtrue
if the previous method shadows the current oneTransactionConfigurationAttributes retrieveConfigurationAttributes(TestContext testContext)
TransactionConfigurationAttributes
for the
specified class
which may optionally declare or inherit
@TransactionConfiguration
. If
@TransactionConfiguration
is not present for the supplied
class, the default values for attributes defined in
@TransactionConfiguration
will be used instead.testContext
- the test context for which the configuration
attributes should be retrieved