During Spring unit test, data written to db but test not seeing the data

Posted by richever on Stack Overflow See other posts from Stack Overflow or by richever
Published on 2010-02-24T07:29:52Z Indexed on 2010/05/22 5:00 UTC
Read the original article Hit count: 279

Filed under:
|

I wrote a test case that extends AbstractTransactionalJUnit4SpringContextTests. The single test case I've written creates an instance of class User and attempts to write it to the database using Hibernate. The test code then uses SimpleJdbcTemplate to execute a simple select count(*) from the user table to determine if the user was persisted to the database or not. The test always fails though. I was suspect because in the Spring controller I wrote, the ability to save an instance of User to the db is successful.

So I added the Rollback annotation to the unit test and sure enough, the data is written to the database since I can even see it in the appropriate table -- the transaction isn't rolled back when the test case is finished.

Here's my test case:

@ContextConfiguration(locations = {
    "classpath:context-daos.xml", 
    "classpath:context-dataSource.xml", 
    "classpath:context-hibernate.xml"})
public class UserDaoTest extends AbstractTransactionalJUnit4SpringContextTests {

  @Autowired
  private UserDao userDao;

  @Test
  @Rollback(false)
  public void teseCreateUser() {
    try {
        UserModel user = randomUser();
        String username = user.getUserName();

        long id = userDao.create(user);

        String query = "select count(*) from public.usr  where usr_name = '%s'";
        long count = simpleJdbcTemplate.queryForLong(String.format(query, username));

        Assert.assertEquals("User with username should be in the db", 1, count);
    }
    catch (Exception e) {
        e.printStackTrace();
        Assert.assertNull("testCreateUser: " + e.getMessage());
    }
  }
}

I think I was remiss by not adding the configuration files.

context-hibernate.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"
   xsi:schemaLocation="
    http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd>

   <bean id="namingStrategy" class="org.springframework.beans.factory.config.FieldRetrievingFactoryBean">
  <property name="staticField">
     <value>org.hibernate.cfg.ImprovedNamingStrategy.INSTANCE</value>
  </property>
   </bean>

   <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean" destroy-method="destroy" scope="singleton">
  <property name="namingStrategy">
     <ref bean="namingStrategy"/>
  </property>

  <property name="dataSource" ref="dataSource"/>

  <property name="mappingResources">
     <list>
        <value>com/company/model/usr.hbm.xml</value>
     </list>
  </property>

  <property name="hibernateProperties">
     <props>
        <prop key="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect</prop>
        <prop key="hibernate.show_sql">true</prop>
        <prop key="hibernate.use_sql_comments">true</prop> 
        <prop key="hibernate.query.substitutions">yes 'Y', no 'N'</prop>
        <prop key="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</prop>
        <prop key="hibernate.cache.use_query_cache">true</prop>
        <prop key="hibernate.cache.use_minimal_puts">false</prop>
        <prop key="hibernate.cache.use_second_level_cache">true</prop>
        <prop key="hibernate.current_session_context_class">thread</prop>
     </props>
  </property>
   </bean>

   <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
  <property name="sessionFactory" ref="sessionFactory"/>
  <property name="nestedTransactionAllowed" value="false" />
   </bean>   

   <bean id="transactionInterceptor" class="org.springframework.transaction.interceptor.TransactionInterceptor">
  <property name="transactionManager">
     <ref local="transactionManager"/>
  </property>

  <property name="transactionAttributes">
     <props>
        <prop key="create">PROPAGATION_REQUIRED</prop>
        <prop key="delete">PROPAGATION_REQUIRED</prop>
        <prop key="update">PROPAGATION_REQUIRED</prop>
        <prop key="*">PROPAGATION_SUPPORTS,readOnly</prop>
     </props>
  </property>
   </bean>      
 </beans>

context-dataSource.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" 
   xsi:schemaLocation="
        http://www.springframework.org/schema/beans 
        http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> 

    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
        <property name="driverClass" value="org.postgresql.Driver" />
        <property name="jdbcUrl"     value="jdbc\:postgresql\://localhost:5432/company_dev" />
        <property name="user"        value="postgres" />
        <property name="password"    value="postgres" />
     </bean>   
</beans>

context-daos.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"
   xsi:schemaLocation="
   http://www.springframework.org/schema/beans 
   http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

   <bean id="extendedFinderNamingStrategy" class="com.company.dao.finder.impl.ExtendedFinderNamingStrategy"/>
   <bean id="finderIntroductionAdvisor"    class="com.company.dao.finder.impl.FinderIntroductionAdvisor"/>

   <bean id="abstractDaoTarget" class="com.company.dao.impl.GenericDaoHibernateImpl" abstract="true" depends-on="sessionFactory">
      <property name="sessionFactory">
         <ref bean="sessionFactory"/>
      </property>

      <property name="namingStrategy">
         <ref bean="extendedFinderNamingStrategy"/>
      </property>
   </bean>

   <bean id="abstractDao" class="org.springframework.aop.framework.ProxyFactoryBean" abstract="true">
      <property name="interceptorNames">
         <list>
           <value>transactionInterceptor</value>
            <value>finderIntroductionAdvisor</value>
         </list>
       </property>
   </bean>

   <bean id="userDao" parent="abstractDao">
     <property name="proxyInterfaces">
       <value>com.company.dao.UserDao</value>
     </property>

  <property name="target">
     <bean parent="abstractDaoTarget">
        <constructor-arg>
           <value>com.company.model.UserModel</value>
        </constructor-arg>
     </bean>
  </property>
  </bean>


</beans>

Some of this I've inherited from someone else. I wouldn't have used the proxying that is going on here because I'm not sure it's needed but this is what I'm working with.

Any help much appreciated.

© Stack Overflow or respective owner

Related posts about unit-testing

Related posts about spring