Unitils, EclipseLink and Spring – Testing your data access layer

We would like to properly test the DAO layer, but there are some issues when using for example the J2EE stack in combination with JPA

Your entity manager will be created by the application server, so for now its not unit testable in an easy way.

That’s where Spring comes in, with a little help from unitils, you will have your set-up in no time!

We will need a unitils.properties, unitils-local.properties, a spring context and a persistence-local.xml

Lets start with the persistence-local.xml. Why cant we use the real one? Most of the settings of the persistence file can be overridden by Spring, but there is one setting that cant be overriden. The transaction-type, it should be RESOURCE_LOCAL

<persistence-unit name="persistence-one" transaction-type="RESOURCE_LOCAL">

In the unitils.properties you do not need to adapt that much. Your default unitils set-up should do. But you have to turn of the transactional proxy.

dataSource.wrapInTransactionalProxy=false

The unitils-properties will look the same as before and will contain the database connections
Our dao’s use the EntityManager. To wire it in we use

@Repository
public class PersonDaoJpaImpl  {
@PersistenceContext

private EntityManager entityManager;

There is only the spring context left now. In there we need a data source, a dialect, an adapter, an entity manager factory and a transaction manager. And of course your other set-up containing the DAO’s (if you have them)

Combined you get something like this (backend-application-test-context.xml)


<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:sdf="http://smals.be/schema/jpa" xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx"
 xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop"
 xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
 http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
 http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee.xsd
 http://smals.be/schema/jpa http://smals.be/schema/jpa/ttjpa.xsd
 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
 http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">

<import resource="classpath:spring/backend-application-context.xml" />

 <bean id="dataSource" class="org.unitils.database.UnitilsDataSourceFactoryBean" />

 <bean id="jpaDialect" class="org.springframework.orm.jpa.vendor.EclipseLinkJpaDialect" />

<bean id="jpaAdapter" class="org.springframework.orm.jpa.vendor.EclipseLinkJpaVendorAdapter">
 <property name="databasePlatform" value="org.eclipse.persistence.platform.database.OraclePlatform" />
 <property name="showSql" value="true" />
 </bean>

 <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
 <property name="persistenceXmlLocation" value="META-INF/persistence-local-test.xml" />
 <property name="jpaVendorAdapter" ref="jpaAdapter" />
 <property name="dataSource" ref="dataSource" />
 </bean>

 <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
 <property name="entityManagerFactory" ref="entityManagerFactory" />
 <property name="jpaDialect" ref="jpaDialect" />
 <property name="dataSource" ref="dataSource" />
 </bean>
</beans>

We import the ‘real’ application context and overwrite the datasource and the entityManagerFactory. So make sure these have the same ID as in the real applicationContext
Your unit test set-up should look like this now

@DataSet
@RunWith(UnitilsJUnit4TestClassRunner.class)
@SpringApplicationContext("backend-application-test-context.xml")
public class PersonDaoJpaImplTest{

@SpringBeanByType
 private PersonDao personDao;

@Test

public void testPersist() throws Exception{

....

}

When testing something that fails you have to specify a rollback. The Transactional annotation is the unitils one, not the spring one!

@Test(expected=Exception.class)
 @Transactional(TransactionMode.DISABLED)
 public void readFailureTest() {

...

}
You can leave a response, or trackback from your own site.
  • disqus_h1iQ8H6sZY

    can you provide a source code example?