org.springframework.test.context.transaction
Class TransactionalTestExecutionListener

java.lang.Object
  extended by org.springframework.test.context.support.AbstractTestExecutionListener
      extended by org.springframework.test.context.transaction.TransactionalTestExecutionListener
All Implemented Interfaces:
TestExecutionListener

public class TransactionalTestExecutionListener
extends AbstractTestExecutionListener

TestExecutionListener that provides support for executing tests within transactions by using the @Transactional and @NotTransactional annotations.

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; whereas, changes to the database during a test that is run with @NotTransactional will not be run within a transaction. Test methods that are not annotated with either @Transactional (at the class or method level) or @NotTransactional 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. @TransactionConfiguration also provides configuration of the bean name of the PlatformTransactionManager that is to be used to drive transactions.

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.

Since:
2.5
Author:
Sam Brannen, Juergen Hoeller
See Also:
TransactionConfiguration, Transactional, NotTransactional, Rollback, BeforeTransaction, AfterTransaction

Nested Class Summary
private static class TransactionalTestExecutionListener.TransactionContext
          Internal context holder for a specific test method.
 
Field Summary
protected  TransactionAttributeSource attributeSource
           
private  TransactionConfigurationAttributes configurationAttributes
           
private static Log logger
           
private  java.util.Map<java.lang.reflect.Method,TransactionalTestExecutionListener.TransactionContext> transactionContextCache
           
private  int transactionsStarted
           
 
Constructor Summary
TransactionalTestExecutionListener()
           
 
Method Summary
 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  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)
          Determines if the supplied method is shadowed by a method in supplied list of previous methods.
private  boolean isShadowed(java.lang.reflect.Method current, java.lang.reflect.Method previous)
          Determines if the supplied current method is shadowed by a previous method.
private  TransactionConfigurationAttributes retrieveConfigurationAttributes(TestContext testContext)
          Retrieves the TransactionConfigurationAttributes for the specified class which may optionally declare or inherit a @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.
 
Methods inherited from class org.springframework.test.context.support.AbstractTestExecutionListener
afterTestClass, beforeTestClass, prepareTestInstance
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

logger

private static final Log logger

attributeSource

protected final TransactionAttributeSource attributeSource

configurationAttributes

private TransactionConfigurationAttributes configurationAttributes

transactionsStarted

private volatile int transactionsStarted

transactionContextCache

private final java.util.Map<java.lang.reflect.Method,TransactionalTestExecutionListener.TransactionContext> transactionContextCache
Constructor Detail

TransactionalTestExecutionListener

public TransactionalTestExecutionListener()
Method Detail

beforeTestMethod

public void beforeTestMethod(TestContext testContext)
                      throws java.lang.Exception
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.

Note that if a @BeforeTransaction method fails, remaining @BeforeTransaction methods will not be invoked, and a transaction will not be started.

Specified by:
beforeTestMethod in interface TestExecutionListener
Overrides:
beforeTestMethod in class AbstractTestExecutionListener
Parameters:
testContext - the test context in which the test method will be executed; never null
Throws:
java.lang.Exception - allows any exception to propagate
See Also:
Transactional, NotTransactional

afterTestMethod

public void afterTestMethod(TestContext testContext)
                     throws java.lang.Exception
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.

@AfterTransaction methods are guaranteed to be invoked even if an error occurs while ending the transaction.

Specified by:
afterTestMethod in interface TestExecutionListener
Overrides:
afterTestMethod in class AbstractTestExecutionListener
Parameters:
testContext - the test context in which the test method was executed; never null
Throws:
java.lang.Exception - allows any exception to propagate

runBeforeTransactionMethods

protected void runBeforeTransactionMethods(TestContext testContext)
                                    throws java.lang.Exception
Run all @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.

Parameters:
testContext - the current test context
Throws:
java.lang.Exception

runAfterTransactionMethods

protected void runAfterTransactionMethods(TestContext testContext)
                                   throws java.lang.Exception
Run all @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.

Parameters:
testContext - the current test context
Throws:
java.lang.Exception

startNewTransaction

private void startNewTransaction(TestContext testContext,
                                 TransactionalTestExecutionListener.TransactionContext txContext)
                          throws java.lang.Exception
Start a new transaction for the supplied 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.

Parameters:
testContext - the current test context
Throws:
TransactionException - if starting the transaction fails
java.lang.Exception - if an error occurs while retrieving the transaction manager

endTransaction

private void endTransaction(TestContext testContext,
                            TransactionalTestExecutionListener.TransactionContext txContext)
                     throws java.lang.Exception
Immediately force a commit or rollback of the transaction for the supplied test context, according to the commit and rollback flags.

Parameters:
testContext - the current test context
Throws:
java.lang.Exception - if an error occurs while retrieving the transaction manager

getTransactionManager

protected final PlatformTransactionManager getTransactionManager(TestContext testContext)
Get the transaction manager to use for the supplied test context.

Parameters:
testContext - the test context for which the transaction manager should be retrieved
Returns:
the transaction manager to use, or null if not found
Throws:
BeansException - if an error occurs while retrieving the transaction manager

isDefaultRollback

protected final boolean isDefaultRollback(TestContext testContext)
                                   throws java.lang.Exception
Determine whether or not to rollback transactions by default for the supplied test context.

Parameters:
testContext - the test context for which the default rollback flag should be retrieved
Returns:
the default rollback flag for the supplied test context
Throws:
java.lang.Exception - if an error occurs while determining the default rollback flag

isRollback

protected final boolean isRollback(TestContext testContext)
                            throws java.lang.Exception
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.

Parameters:
testContext - the test context for which the rollback flag should be retrieved
Returns:
the rollback flag for the supplied test context
Throws:
java.lang.Exception - if an error occurs while determining the rollback flag

getSuperClasses

private java.util.List<java.lang.Class<?>> getSuperClasses(java.lang.Class<?> clazz)
Gets all superclasses of the supplied class, including the class itself. The ordering of the returned list will begin with the supplied class and continue up the class hierarchy.

Note: This code has been borrowed from org.junit.internal.runners.TestClass#getSuperClasses(Class) and adapted.

Parameters:
clazz - the class for which to retrieve the superclasses.
Returns:
all superclasses of the supplied class.

getAnnotatedMethods

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.

Note: This code has been borrowed from org.junit.internal.runners.TestClass#getAnnotatedMethods(Class) and adapted.

Parameters:
clazz - the class for which to retrieve the annotated methods
annotationType - the annotation type for which to search
Returns:
all annotated methods in the supplied class and its superclasses

isShadowed

private boolean isShadowed(java.lang.reflect.Method method,
                           java.util.List<java.lang.reflect.Method> previousMethods)
Determines if the supplied method is shadowed by a method in supplied list of previous methods.

Note: This code has been borrowed from org.junit.internal.runners.TestClass#isShadowed(Method,List).

Parameters:
method - the method to check for shadowing
previousMethods - the list of methods which have previously been processed
Returns:
true if the supplied method is shadowed by a method in the previousMethods list

isShadowed

private boolean isShadowed(java.lang.reflect.Method current,
                           java.lang.reflect.Method previous)
Determines if the supplied current method is shadowed by a previous method.

Note: This code has been borrowed from org.junit.internal.runners.TestClass#isShadowed(Method,Method).

Parameters:
current - the current method
previous - the previous method
Returns:
true if the previous method shadows the current one

retrieveConfigurationAttributes

private TransactionConfigurationAttributes retrieveConfigurationAttributes(TestContext testContext)
Retrieves the TransactionConfigurationAttributes for the specified class which may optionally declare or inherit a @TransactionConfiguration. If a TransactionConfiguration annotation is not present for the supplied class, the default values for attributes defined in TransactionConfiguration will be used instead.

Parameters:
clazz - the Class object corresponding to the test class for which the configuration attributes should be retrieved
Returns:
a new TransactionConfigurationAttributes instance