public class TransactionalTestExecutionListener extends AbstractTestExecutionListener
TestExecutionListener
that provides support for executing tests
within transactions by honoring the
@Transactional
annotation. Expects a PlatformTransactionManager
bean to be defined in the
Spring ApplicationContext
for the test.
Changes to the database during a test that is run with @Transactional
will be run within a transaction that will, by default, be automatically
rolled back after completion of the test. Test methods that are not
annotated with @Transactional
(at the class or method level) will not
be run within a transaction.
Transactional commit and rollback behavior can be configured via the
class-level @TransactionConfiguration
and
method-level @Rollback
annotations.
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,
TransactionManagementConfigurer
can be implemented in an
@Configuration
class.
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
and
@AfterTransaction
.
TransactionConfiguration
,
TransactionManagementConfigurer
,
Transactional
,
Rollback
,
BeforeTransaction
,
AfterTransaction
Modifier and Type | Class and Description |
---|---|
private static class |
TransactionalTestExecutionListener.TransactionContext
Internal context holder for a specific test method.
|
Modifier and Type | Field and Description |
---|---|
protected TransactionAttributeSource |
attributeSource |
private TransactionConfigurationAttributes |
configurationAttributes |
private static java.lang.Boolean |
DEFAULT_DEFAULT_ROLLBACK |
private static java.lang.String |
DEFAULT_TRANSACTION_MANAGER_NAME |
private static Log |
logger |
private java.util.Map<java.lang.reflect.Method,TransactionalTestExecutionListener.TransactionContext> |
transactionContextCache |
private int |
transactionsStarted |
Constructor and Description |
---|
TransactionalTestExecutionListener() |
Modifier and Type | Method and Description |
---|---|
void |
afterTestMethod(TestContext testContext)
If a transaction is currently active for the test method of 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 void |
endTransaction(TestContext testContext,
TransactionalTestExecutionListener.TransactionContext txContext)
Immediately force a commit or rollback of the
transaction for the supplied
test context , according
to the commit and rollback flags. |
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. |
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 . |
private void |
startNewTransaction(TestContext testContext,
TransactionalTestExecutionListener.TransactionContext txContext)
Start a new transaction for the supplied
test context . |
afterTestClass, beforeTestClass, prepareTestInstance
private static final Log logger
private static final java.lang.String DEFAULT_TRANSACTION_MANAGER_NAME
private static final java.lang.Boolean DEFAULT_DEFAULT_ROLLBACK
protected final TransactionAttributeSource attributeSource
private final java.util.Map<java.lang.reflect.Method,TransactionalTestExecutionListener.TransactionContext> transactionContextCache
private TransactionConfigurationAttributes configurationAttributes
private volatile int transactionsStarted
public void beforeTestMethod(TestContext testContext) throws java.lang.Exception
test context
is
configured to run within a transaction, this method will run
@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
test context
, this method will end the transaction
and run @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
private void startNewTransaction(TestContext testContext, TransactionalTestExecutionListener.TransactionContext txContext) throws java.lang.Exception
test context
.
Only call this method if endTransaction(org.springframework.test.context.TestContext, org.springframework.test.context.transaction.TransactionalTestExecutionListener.TransactionContext)
has been called or if no
transaction has been previously started.
testContext
- the current test contextTransactionException
- if starting the transaction failsjava.lang.Exception
- if an error occurs while retrieving the transaction managerprivate void endTransaction(TestContext testContext, TransactionalTestExecutionListener.TransactionContext txContext) throws java.lang.Exception
test context
, according
to the commit and rollback flags.testContext
- the current test contextjava.lang.Exception
- if an error occurs while retrieving the transaction managerprotected 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
.testContext
- the test context for which the transaction manager
should be retrievednull
if not foundBeansException
- if an error occurs while retrieving the 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