Testing through Spring with rollbacks
If you download the spring framework with dependencies, one of the modules included is the spring-test.
spring
- Convenient jar file combining all standard modules (except for the test module and the Spring MVC support)
- Also includes the AOP Alliance interfaces (as a convenience)!
- Does not include contents of spring-aspects.jar, spring-test.jar and spring-webmvc*.jar!
spring-test
- Contents: test context framework, JUnit support, JNDI mocks, Servlet API mocks, Portlet API mocks
- Dependencies: spring-core, (spring-context, spring-jdbc, spring-web, JUnit, Servlet API, Portlet API)
As the spring documentation mentions, for unit testing transactional systems you can achieve rollback of your tests pretty easily:
Typically you will extend the subclass, AbstractTransactionalDataSourceSpringContextTests. This class also requires that a DataSource bean definition – again, with any name – be present in the application context. It creates a JdbcTemplate instance variable, that is useful for convenient querying, and provides handy methods to delete the contents of selected tables (remember that the transaction will roll back by default, so this is safe to do).
This problem was identified with MySql.
Nice article here on spring test
This link tells us about the spring testing method calls
AbstractTransactionalDataSourceSpringContextTests superclass provides the following services: Injects test dependencies, meaning that we don't need to perform application context lookups. Injection uses autowiring by type. Executes each test method in its own transaction, which is automatically rolled back by default. This means that even if tests insert or otherwise change database state, there is no need for a teardown or cleanup script. If you want a transaction to commit--unusual, but useful if you want a particular test to populate the database, for example--you can call the setComplete() method inherited from AbstractTransactionalSpringContextTests. This will cause the transaction to commit instead of roll back. There is also convenient ability to end a transaction before the test case ends, through calling the endTransaction() method. This will roll back the transaction by default, and commit it only if setComplete() had previously been called. Provides useful inherited protected fields, such as a JdbcTemplate that can be used to verify database state after test operations, or verify the results of queries performed by application code. An ApplicationContext is also inherited, and can be used for explicit lookup if necessary.
All the Spring Test Life Cycle Methods
- getConfigLocations
- setDataSource
- setTransactionManager
- onSetUpBeforeTransaction
- onSetUpInTransaction
- onTearDownInTransaction
- endTransaction
- onTearDownAfterTransaction
Now onto the 2.5 way of testing:
org.springframework.test.context – Spring TestContext Framework which provides annotation-driven unit and integration testing support that is agnostic of the actual testing framework in use.
Spring 2.5 continues this rich and convenient testing framework, while now removing the requirement that your unit tests extend Spring framework tests. Instead of subclassing, it uses java annotations.
Related links:
The IBatis Model
Been a while since I started first looking at IBatis. The Spring Framework has a sample application named JPetstore (available in the core download) that gives you an example of IBatis, Spring, and Struts 1.x .
Different Spring Ibatis SQLMaps approaches:
Use Of Annotations
Implementing DAOs based on plain iBATIS API
<bean
id=”dataSource”
class=”org.springframework.jdbc.datasource.SingleConnectionDataSource”
destroy-method=”destroy”
>
<bean id=”transactionManager”
class=”org.springframework.jdbc.datasource.DataSourceTransactionManager”>
<property name=”dataSource” ref=”dataSource”/>
</bean>
<bean id=”sqlMapClient” class=”org.springframework.orm.ibatis.SqlMapClientFactoryBean”>
<property name=”configLocation” value=”classpath:/sqlmap-config.xml”/>
<property name=”dataSource” ref=”dataSource”/>
</bean>
<?xml version=”1.0″ encoding=”UTF-8″?>
<!DOCTYPE sqlMapConfig PUBLIC
“-//ibatis.apache.org//DTD SQL Map Config 2.0//EN”
“http://ibatis.apache.org/dtd/sql-map-config-2.dtd”>
<sqlMapConfig>
<settings defaultStatementTimeout=”5″ />
<sqlMap resource=”MyType.xml” />
</sqlMapConfig>
You can actually omit the ‘transaction-manager’ attribute in the <tx:annotation-driven/> tag if the bean name of the PlatformTransactionManager that you want to wire in has the name ‘transactionManager’.
<!– Instructs Spring to perfrom declarative transaction managemenet on annotated classes –>
<tx:annotation-driven/>
@Autowired
public void setSqlMapClient(SqlMapClient sqlMapClient) {
iBatisTemplate = new SqlMapClientTemplate(sqlMapClient);
}
@@Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW)
- The @Transactional annotation may be placed before an interface definition, a method on an interface, a class definition, or a public method on a class. However, please note that the mere presence of the @Transactional annotation is not enough to actually turn on the transactional behavior.
public MyType insertMyType(MyType myType) {
MyType myType = null;
myType= (MyType) iBatisTemplate.insert(“insertIntoMyType”, MyType;
return myType;
}
Use Of Spring’s DaoSupport Class
<bean
id=”dataSource”
class=”org.apache.commons.dbcp.BasicDataSource”
destroy-method=”close”
>
<bean id=”sqlMapClient” class=”org.springframework.orm.ibatis.SqlMapClientFactoryBean”>
<property name=”configLocation” value=”classpath:/sqlmap-config.xml”/>
<property name=”dataSource” ref=”dataSource”/>
</bean>
<?xml version=”1.0″ encoding=”UTF-8″?>
<!DOCTYPE sqlMapConfig PUBLIC “-//iBATIS.com//DTD SQL Map Config 2.0//EN”
“http://www.ibatis.com/dtd/sql-map-config-2.dtd”>
<sqlMapConfig>
<settings useStatementNamespaces=”true” />
<sqlMap resource=”person.xml” />
</sqlMapConfig>
PersonDaoIbatisImpl extends SqlMapClientDaoSupport
public void addPerson(Person person) {
Long id = (Long) this.getSqlMapClientTemplate().insert(“person.insert”,
person);
person.setId(id);
}
- org.springframework.orm.ibatis.support.SqlMapClientDaoSupport – Instead of a plain SqlMapClient, you can also pass a preconfigured SqlMapClientTemplate instance in. This allows you to share your SqlMapClientTemplate configuration for all your DAOs