在Spring单元测试期间,数据写入db但是测试没有看到数据

时间:2010-02-24 07:29:53

标签: unit-testing spring

我写了一个扩展AbstractTransactionalJUnit4SpringContextTests的测试用例。我编写的单个测试用例创建了一个类User实例,并尝试使用Hibernate将其写入数据库。然后,测试代码使用SimpleJdbcTemplate从用户表执行简单的选择计数(*),以确定用户是否持久保存到数据库。但测试总是失败。我很怀疑,因为在我写的Spring控制器中,将用户实例保存到数据库的能力是成功的。

所以我将Rollback注释添加到单元测试中,果然,数据被写入数据库,因为我甚至可以在相应的表中看到它 - 当测试用例完成时,事务不会回滚。

这是我的测试用例:

@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());
    }
  }
}

我认为我没有添加配置文件。

上下文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>

上下文data​​Source.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>

上下文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>

其中一些我从别人那里继承了。我不会使用正在进行的代理,因为我不确定它是否需要,但这正是我正在使用的。

任何帮助都非常感激。

2 个答案:

答案 0 :(得分:1)

IIRC,Hibernate(和其他O / R映射器)延迟数据库INSERT和UPDATE语句,直到事务提交。然后SELECT没有看到数据,因为它尚未写入。尝试明确请求会话刷新。

另见文档以获得解释和示例: http://docs.jboss.org/hibernate/core/3.3/reference/en/html/objectstate.html#objectstate-flushing

答案 1 :(得分:0)

transactionInterceptor不会自动提交吗?

http://www.docjar.com/html/api/org/springframework/transaction/interceptor/TransactionInterceptor.java.html

第117行:

commitTransactionAfterReturning(txInfo);

默认情况下,刷新模式应该是auto,因此执行commit时应该有一个隐式刷新。我有同样的问题,不得不通过手动调用flush来解决它。这是非常不满意的,因为我的现有代码在迁移到Spring transation manager之前依赖于自动刷新。我希望有一种方法可以告诉org.springframework.orm.hibernate3.HibernateTransactionManager在提交后进行刷新。