TechnoBuzz

A Techno Blog, mainly about Java

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

API

  • getConfigLocations
  • setDataSource
  • setTransactionManager
  • onSetUpBeforeTransaction
  • onSetUpInTransaction
  • onTearDownInTransaction
  • endTransaction
  • onTearDownAfterTransaction

example scenario:

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:

August 24, 2008 Posted by | IoC, J2EE | 1 Comment

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”&gt;
<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”&gt;
<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);
}

August 17, 2008 Posted by | Uncategorized | 1 Comment