0

すべて、Hibernate を使用する Dao の単体テストを作成しようとしています。私もSpringを使用しているので、AbstractTransactionalDataSourceSpringContextTestsを拡張し、onSetUpInTransactionメソッドの各テストの前にDBUnitを使用してデータベースにデータを挿入しようとしています。

ログから、DbUnit が onSetUpInTransaction にデータを正常に挿入できることがわかります。ただし、Dao (したがって、Hibernate) を使用してそのデータ (testGetPersonById2) にアクセスしようとするテスト メソッドを実行すると、すべて同じトランザクションで発生するはずですが、データが見つかりません。テスト メソッドの実行が終了すると (失敗します)、AbstractTransactionalDataSourceSpringContextTests からのログ ステートメントで、トランザクションが正しくロールバックされることがわかります。

onSetUpInTransaction と Hibernate セッションは異なるトランザクションを使用している必要があるようですが、その理由はわかりません。このような作業の例はありますか? 私が欠けているものについてのアドバイスは?

ここに私がこれまでに持っているものがあります:

public class PersonDaoTest extends AbstractTransactionalDataSourceSpringContextTests{

    private Log logger = LogFactory.getLog(PersonDaoTest.class);

    private PersonDaoImpl personDao;

    @Override
    public void onSetUpInTransaction() throws Exception {
    // Load test data using DBUnit
    super.onSetUpBeforeTransaction();
        DataSource ds = jdbcTemplate.getDataSource()
    Connection con = DataSourceUtils.getConnection(ds);
    IDatabaseConnection dbUnitCon = new DatabaseConnection(con);
    DatabaseConfig config = dbUnitCon.getConfig();
    config.setFeature("http://www.dbunit.org/features/qualifiedTableNames",
        true);

        //This dataset contains a single entry in the Persons table,
        // a new person with Id = 998877665, it gets inserted successfully
    IDataSet dataSet = new FlatXmlDataSet(new FileInputStream(
        "./PersonDaoTest.xml"));
    logger.warn("dataSet = " + dataSet);
    try {
        DatabaseOperation.REFRESH.execute(dbUnitCon, dataSet);
        SessionFactoryUtils.getSession(getSessionFactory(), false).flush();

    } finally {
        DataSourceUtils.releaseConnection(con, ds);
    }

    }

     //This test PASSES, because the Person with Id = 9 already
     //exists in the database, it does not rely on the data being set up in the        
     // onSetUpInTransaction method 
     @Test
     public void testGetPersonById() {

     Person person = personDao.findById(9L);
     assertNotNull("person should not be null", person);

     }

    //This test FAILS at the assertNotNull line, because
    //no Person with Id = 998877665 exists in the database,
    //even though that Person was inserted 
    //in the onSetUpInTransaction  method - it seems
    //that hibernate cannot see that insertion.
    @Test
    public void testGetPersonById2() {

    Person person = personDao.findById(998877665L);
    assertNotNull("person should not be null", person);

    }

更新: これが私の春の設定です:

<bean id="propertyConfigurer"       class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="locations">
            <list>
                <value>classpath:jdbc.properties</value>
            </list>
        </property>
    </bean>

<bean id="dataSource" class="com.p6spy.engine.spy.P6DataSource">
  <constructor-arg>
    <bean id="basicDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
   <property name="driverClassName">
     <value>${jdbc.driverClassName}</value>
    </property>
    <property name="url">
       <value>${jdbc.url}</value>
    </property>
    <property name="username">
       <value>${jdbc.username}</value>
    </property>
     <property name="password">
       <value>${jdbc.password}</value>
      </property>
   </bean>
  </constructor-arg>
</bean>

<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource"/>
</bean>


<!-- Hibernate SessionFactory -->
    <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
        <property name="dataSource"><ref bean="dataSource"/></property>

        <property name="configLocation">
             <value>classpath:hibernate.cfg.xml</value>
        </property>

        <property  name="configurationClass">
            <value>org.hibernate.cfg.AnnotationConfiguration</value>
        </property>

        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.show_sql">false</prop>
                <prop key="hibernate.dialect">org.hibernate.dialect.Oracle9Dialect</prop>
                <prop key="hibernate.cache.use_query_cache">false</prop>
                <prop key="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</prop>
                <prop key="hibernate.cache.query_cache_factory">org.hibernate.cache.StandardQueryCacheFactory</prop>
            </props>
        </property>
    </bean>

    <!-- The Hibernate interceptor 
    <bean id="hibernateInterceptor" class="org.springframework.orm.hibernate3.HibernateInterceptor">
        <property name="sessionFactory"><ref bean="sessionFactory"/></property>
    </bean>-->

     <bean id="personDao" class="my.dao.PersonDaoImpl">
        <property name="sessionFactory"><ref bean="sessionFactory"/></property>         
    </bean> 
4

2 に答える 2

1

同様の問題がありました。これが私がそれを解決した方法です。抽象テストケース クラスにコードを追加し、「dataSource」という名前のデータ ソースを追加しました。これにより、それを使用してテスト データを挿入し、そのデータ ソースを使用してテスト SQL を作成できました。個々のデータソース datasource1 および datasource2 は、問題なく dao Bean に正しく注入されました。

@Override
protected String[] getConfigLocations() 
{
    setAutowireMode(AUTOWIRE_BY_NAME);
    setDependencyCheck(false);
    return new String[] { "classpath:configuration/myappxxx-test-application-context.xml" };
}
于 2012-12-12T16:08:15.520 に答える
1

これにさらに時間を費やしましたが、 onSetUpInTransaction メソッドを使用しようとしたときに機能するものを見つけることができませんでした。代わりに onSetUpBeforeTransaction と onTearDownAfterTransaction を使用するように切り替えました。onSetUpBeforeTransaction メソッドはデータベースへのデータ挿入をコミットすることになり、そのデータは onTearDownAfterTransaction でクリーンアップする必要があるため、これは必ずしも理想的ではありません。ただし、各テストは引き続き独自のトランザクションで動作するため、テスト自体はデータを必要に応じて挿入および更新し、それらの変更をすべてロールバックできます。したがって、テストで新しいデータが挿入されたときにクリーンアップするために特別なことをする必要はありません。つまり、目標の 1 つを達成したということです。

于 2010-06-30T15:05:36.120 に答える