Tuesday, 22nd June 2010
The new frontier for learning Java

Spring Junit With Automatic Transactional Rollback Support

From WikiJava

Jump to: navigation, search



This page is or contains a derivative version of a portion of this GFDL content
The article was originally sourced from Ganesh Gowtham.

Ganesh Gowtham's Website

Contents

Summary

In Nomal Traditional we write huge amount of Junit as part of TDD Test Driven Development which means writing the Junit first and write

the class which needs to be tested .

We write Junit to test the Dao classes which interact with Database quite often , those methods in dao will manipulate the data and corrupt the data in database after method execution ,one way to avoid is to use the rollback the transaction after the method execution .

Infact the Spring's AbstractTransactionalSpringContextTests does automatic rollback each time after the method execution there by reducing the boiler plate code to rollback the transaction.

In spring_test.xml i had used autowire byType which means no need to set beans with <property ref="beanID"/> manually , based on the autowire Spring Frameworks automatically injects during init period.

AbstractTransactionalSpringContextTests

Convenient superclass for tests that should occur in a transaction, but normally will roll the transaction back on the completion of each test.

This is useful in a range of circumstances, allowing the following benefits:

  • Ability to delete or insert any data in the database, without affecting other tests
  • Providing a transactional context for any code requiring a transaction
  • Ability to write anything to the database without any need to clean up.

This class is typically very fast, compared to traditional setup/teardown scripts.

If data should be left in the database, call the setComplete() method in each test. The defaultRollback() property, which defaults to true, determines whether transactions will complete by default.

Requires a single bean in the context implementing the PlatformTransactionManager interface. This will be set by the superclass's Dependency Injection mechanism. If using the superclass's Field Injection mechanism, the implementation should be named "transactionManager". This mechanism allows the use of this superclass even when there's more than one transaction manager in the context.

IPersonDao

package com.jpratice.spring.junit.dao;
public interface IPersonDao {
   void savePerson(long empId, String empName);
}

PersonDao

package com.jpratice.spring.junit.dao.impl;
 
import org.springframework.jdbc.core.JdbcTemplate;
 
import com.jpratice.spring.junit.dao.IPersonDao;
 
public class PersonDao extends JdbcTemplate implements IPersonDao {
 
   private final String INSERT_SQL = "INSERT INTO EMP (id,name) values (? ,?)";
 
   public void savePerson(long empId, String empName) {
      Object[] args = { empId, empName };   
      update(INSERT_SQL, args);
  }
}

PersonDaoTest which uses AbstractTransactionalSpringContextTests

package com.jpratice.spring.junit;
 
import org.springframework.test.AbstractTransactionalSpringContextTests;
 
import com.jpratice.spring.junit.dao.IPersonDao;
 
/**
 * Copyright 2009 @ jPractices v 1.0
 * @SVN URL : http://jpractices.googlecode.com
 * @author Ganesh Gowtham
 * @Homepage : http://sites.google.com/site/ganeshgowtham
 */
public class PersonDaoTest extends AbstractTransactionalSpringContextTests {
   private final String CONTEXT_FILE_PATH = "c:/config/spring/spring_test.xml";
   private IPersonDao personDao;
   private long empId = 2229;
   private String empName = "Ganesh Gowtham";
 
   public IPersonDao getPersonDao() {
      return personDao;
   }
 
   /**
    * Implementation of IPersonDao will be injected by Spring Frmk based on file configured in
    * CONTEXT_FILE_PATH
    *
    * @param personDao
    */
   public void setPersonDao(IPersonDao personDao) {
      this.personDao = personDao;
   }
 
   /**
    * Comma seperated path of various spring context xml's
    */
   protected String[] getConfigLocations() {
      return new String[] { CONTEXT_FILE_PATH };
   }
 
   /**
    * Save The Tx , by default tx will be rollbacked by Spring Frmk
    */
   private void saveTransaction() {
      setComplete();
   }
 
   public void testInsertPerosnWithRollback() {
      getPersonDao().savePerson(empId, empName);
   }
 
   public void testInsertPerson() {
      getPersonDao().savePerson(empId, empName);
      saveTransaction();        
   }    
}

spring_test.xml which uses autowire='byType'

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans default-autowire="byType">
   <bean class="org.apache.commons.dbcp.BasicDataSource"
     destroy-method="close">
     <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" />
     <property name="url"
      value="jdbc:oracle:thin:@dbserver:portNO:dbName" />
     <property name="username" value="scott" />
     <property name="password" value="elephant" />
     <property name="defaultAutoCommit" value="true" />
     <property name="maxActive" value="30" />
    </bean>
    <bean class="com.jpratice.spring.junit.PersonDaoTest"/>
    <bean class="com.jpratice.spring.junit.dao.impl.PersonDao"/>
</beans>

References

Spring Framework Autowire
Spring Framework
Junit
What is AbstractTransactionalSpringContextTests


Comments from the users

To be notified via mail on the updates of this discussion you can login and click on watch at the top of the page


Title (required):

Website:

Comment: