0

永続化コードの単体テストを作成しようとしています。JPA アノテーション付きの Hibernate を使用しています。persistence.xml はありません (JPA 単体テストに関するすべての記事で使用されています)。多くの永続化クラスがあり、それらすべての休止状態の初期化に時間がかかるため、Spring を使用したり、persistence.xml を作成したりしたくないため、明示的に休止状態にするクラスを追加したいと考えています。

またconfiguration.createSessionFactory()、私のDAOにはSpringによって注入されたJPA EntityManagerがあるため、Hibernate単体テスト記事で推奨されているように使用できません。

だから私は使用していEntityManagerFactoryImplます:

AnnotationConfiguration configuration = new AnnotationConfiguration();

configuration.setProperty(Environment.DRIVER,"org.apache.derby.jdbc.EmbeddedDriver");
configuration.setProperty(Environment.URL,"jdbc:derby:memory:srf.derby;create=true");
configuration.setProperty(Environment.USER, "");
configuration.setProperty(Environment.DIALECT, DerbyDialect.class.getName());
configuration.setProperty(Environment.SHOW_SQL, "true");
configuration.setProperty(Environment.HBM2DDL_AUTO, "create-drop");
configuration.setProperty( Environment.AUTOCOMMIT, "true");

configuration.addAnnotatedClass(MyPersistentClass.class);

MyHibernateDAO dao = new MyHibernateDAO();

EntityManagerFactoryImpl entityManagerFactory = new EntityManagerFactoryImpl(
                                  configuration.buildSessionFactory(),
                                  PersistenceUnitTransactionType.RESOURCE_LOCAL, 
                                  true, 
                                  null, 
                                  configuration);

dao.setEntityManager(entityManagerFactory.createEntityManager());

これは問題ないように見えますが、何らかの理由で db への挿入は発生しませんが、すべての選択は問題ありません (SQL を true に表示しました)。AUTOCOMMIT が false のようです (本番環境では、Spring がトランザクションを管理します)。ご覧のとおり、構成を AUTOCOMMIT true に設定し、EntityManager から JDBC 接続を取得し、デバッガーで自動コミットが true であることを確認しましたが、単体テストでトランザクションを明示的に開始してコミットした場合にのみ挿入が起動されます。

私が間違っていることは何ですか?自動コミットでテストを実行するにはどうすればよいですか?

ありがとうございました!

4

1 に答える 1

0

DAO コードで @Transactional-annotations を使用していると思います。問題は、EntityManager と DAO を手動でインスタンス化すると、それらのアノテーションに対応するための TransactionManager やプロキシがないため、トランザクションが自動的に作成されないことです。

Spring ApplicationContext を作成せずに、または Springs の JUnit ランナーなどを使用せずに、テストでデータベースにデータを本当にコミットしたい場合は、トランザクションを自分で処理する必要があると思います (ただし、間違っている可能性があります)。おそらく最も簡単な方法は、次のようなテストを拡張するベースクラスを作成することです。

import javax.persistence.EntityManager;

import org.hibernate.cfg.AnnotationConfiguration;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;

public abstract class TransactionalTestBase
{
    private EntityManager em;

    protected abstract Class<?>[] getAnnotatedClasses();

    @BeforeClass
    public void setupEntityManager()
    {
        //Build your basic configuration

        AnnotationConfiguration configuration = new AnnotationConfiguration();
        //configuration.setProperty(
        //...

        //Ask the implementing class for the entity-classes
        for(Class<?> clazz : getAnnotatedClasses())
        {
            configuration.addAnnotatedClass(clazz);
        }

        //Set up your entitymanager here

    }

    @Before
    public void beforeTest()
    {
        em.getTransaction().begin();
    }

    @After
    public void afterTest()
    {
        if(em.getTransaction().getRollbackOnly())
        {
            em.getTransaction().rollback();
        }
        else
        {
            em.getTransaction().commit();
        }
    }

    @AfterClass
    public void tearDownEntityManager()
    {
        em.flush();
        em.clear();
        em.close();
        em = null;
    }
}

これからさらにクラスを拡張すると、@BeforeClass、@Before などをさらに追加できることに注意してください。-注釈、それらは継承順に実行されます。

テストで Spring を活用する場合は、http://static.springsource.org/spring/docs/3.1.x/spring-framework-reference/html/testing.htmlを参照してください。

于 2012-01-29T09:45:48.973 に答える