31 Aug 2010
I've recently done a proof of concept using RabbitMQ, Spring AMQP and Spring Integration. This...
21 Jul 2010
In over ten years of experience building software, there are patterns and nuances that you...
13 Jul 2010
I set out to find an elegant solution to providing growl notifications for a JRuby...
05 May 2010
I've started playing around with Heroku lately and ran into an issue when I created...
30 Apr 2010
I've been meaning to investigate something that came to mind a while back and just...

Testing Your App Using Spring's AbstractTransactionalJUnit4SpringContextTests

Published: 02 Oct 2009

AbstractTransactionalJUnit4SpringContextTests is a pretty long class name but it makes easy work of testing a Spring application which uses a database. This post will walk through a quick example of how to use the class while demonstrating it’s usefulness. Let’s get to the code.

Extending AbstractTransactionalJUnit4SpringContextTests

The AbstractTrkrCoreTests class below extends AbstractTransactionalJUnit4SpringContextTests and sets up a few things needed by this application including the datasource and the Spring context configuration.

 1 @ContextConfiguration(locations={
 2     "classpath:spgConfDataContext.xml",
 3     "classpath:liveCoreContext.xml",
 4     "classpath:trkrCoreContext.xml",
 5     "classpath:trkrCoreTestContext.xml"
 6 })
 7 @TransactionConfiguration(transactionManager = "ebondTransactionManager")  
 8 public abstract class AbstractTrkrCoreTests extends AbstractTransactionalJUnit4SpringContextTests {
 9 
10   @Autowired
11   protected AnalysisContextDaoSqlMap analysisContextDaoSqlMap;
12   @Autowired
13   protected ModelDaoSqlMap modelDaoSqlMap;
14   @Autowired
15   protected TrustDaoSqlMap trustDaoSqlMap;
16 
17   @Override
18   @Autowired
19 public void setDataSource(@Qualifier(value = "ebondDataSource") DataSource dataSource) {
20   this.simpleJdbcTemplate = new SimpleJdbcTemplate(dataSource);
21 }
22 ...

  1. @ContextConfiguration - accepts multiple locations of other Spring context files required for tests.
  2. TransactionConfiguration - is optional if you only have one transaction manager Spring bean definition. In this application there are several defined so this annotation is added here to define which transaction manager to use.
  3. @Autowired - sets up various DAOs commonly needed by tests which extend this class.
  4. @Qualifier - is used in the setDataSource method to choose a specific data source where there are more than one available from the Spring configuration. This annotation can be used for a class property or a method parameter to qualify which bean should be injected.

Test Implementation

Next is an actual test class:

 1 ...imports omitted for brevity...
 2 
 3 public class TrustDaoSqlMapTest extends AbstractTrkrCoreTests {
 4 
 5   private static final Logger logger = Logger.getLogger(TrustDaoSqlMapTest.class);
 6 
 7   private Date createdDate;
 8   private List<Model> models;
 9   private static boolean doSetup = true;
10 
11   @Before
12   public void before() throws Exception {
13     createdDate = getMockCreatedDate();
14     models = modelDaoSqlMap.getAll();
15     if (doSetup) {
16       deleteFromTables("trkr_trust", "trkr_iioc_trust_calc", "trkr_iioc_trust" );
17       executeSqlScript("classpath:sql/populate_trkr_trust.sql", false);
18       executeSqlScript("classpath:sql/populate_trkr_iioc_trust.sql", false);
19       doSetup = false;
20     }
21   }
22 
23   @Test
24   public void testGetByCreated() throws Exception {
25     List<Trust> trusts = trustDaoSqlMap.getByCreated(createdDate);
26     doTrustAssertions(trusts);
27   }
28 
29 ...
  1. @Before - a JUnit annotation which will be called prior to each @Test. The doSetup property here just ensures that the database setup is done just once for the tests in this class.
  2. deleteFromTables - helper method from AbstractTransactionalJUnit4SpringContextTests which will delete all the records in the tables passed to it. This all happens in the same transaction in which the tests are run. What this means is that the tables in question will be in the same state that they were before the test was run. This is especially helpful if you don’t have a database sandbox and instead the database is shared among one or more developers.
  3. executeSqlScript - is another helper method which allows you to execute arbitrary SQL needed by the tests. In this case, two scripts are called to populate some test data.
  4. @Test - a JUnit annotation used to indicate a method as a test.

Caveats

  1. The ordering of the parameters for deleteFromTables are important if foreign keys and/or other constraints are in place.
  2. If you’re testing against a database which has a lot of data the deleteFromTables method may take a long time to execute. If the data volume is large enough, you may want to think about either reducing the number of records in the tables or simply using the data that’s already there instead of deleting and inserting your own test data.

blog comments powered by Disqus