I have the following test case:
@ContextConfiguration("/spring/test-context.xml")
@TransactionConfiguration(transactionManager="txManager")
@Transactional()
public class MyEntityDaoTestCase extends AbstractJUnit4SpringContextTests {
@Autowired
private MyEntityDao dao;
@Test
public void testSave_success() {
MyEntity e = new MyEntity();
dao.save(e);
MyEntity result = dao.findById(e.getId());
assertNotNull(result);
}
}
My DAO definition has as follows:
public abstract class MyEntityDAO {
@PersistenceContext
private EntityManager mEntityManager;
public void save(MyEntity entity) {
mEntityManager.persist(entity);
}
public MyEntity findById(Long id) {
return mEntityManager.find(mEntityClass, id);
}
}
My Spring config is the following:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
<!--
Bean post-processor for JPA annotations
-->
<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"/>
<!--
JPA entity manager factory
-->
<bean id="jpaEntityManagerFactory" class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">
<property name="persistenceUnitName" value="unit-test-pu"/>
</bean>
<!--
Transaction manager
-->
<bean id="txManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="jpaEntityManagerFactory"/>
</bean>
<!--
Enable the configuration of transactional behavior based on annotations
-->
<tx:annotation-driven transaction-manager="txManager"/>
<!--
DAO instance beans
-->
<bean id="mockEntityDao" class="mypackage.MyEntityDao"></bean>
</beans>
I get no errors while executing my test but it won’t pass. It looks like the findById() method will not find the entity in the database. Can anyone advise on how to correctly test this case?
EDIT:
My JPA provider is hibernate. I am using an in-memory HSQLDB for my unit tests and have the following configuration:
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
version="2.0">
<persistence-unit name="unit-test-pu" transaction-type="RESOURCE_LOCAL">
<properties>
<property name="javax.persistence.jdbc.driver" value="org.hsqldb.jdbcDriver"/>
<property name="javax.persistence.jdbc.user" value="sa"/>
<property name="javax.persistence.jdbc.password" value=""/>
<property name="javax.persistence.jdbc.url" value="jdbc:hsqldb:."/>
<property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect"/>
<property name="hibernate.archive.autodetection" value="class"/>
<property name="hibernate.show_sql" value="true"/>
<property name="hibernate.format_sql" value="true"/>
<property name="hibernate.hbm2ddl.auto" value="create"/>
</properties>
</persistence-unit>
</persistence>
If you follow TDD strictly you should not use an in memory database but instead have everything mocked. The problem is that the persist method returns void. So you can not test the correct response (an entity with an id generated by a database) One way to work around this is to us the Mockito doAnswer method, here an example:
A complete explanation can be found on my blog post.