web-dev-qa-db-ja.com

JUnitのSpringでサービスをテストするときにデータベーストランザクションをロールバックする方法

DAOとサービスのテストに問題はありませんが、INSERTsまたはUPDATEsをテストするとき、データベースに影響を与えずにトランザクションをロールバックします。

サービス内で_@Transactional_を使用してトランザクションを管理しています。知りたいのですが、トランザクションが正常かどうかを知ることはできますが、データベースを変更しないようにロールバックしますか?

これは私のテストです:

_@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:/META-INF/spring.cfg.xml")
@TransactionConfiguration(defaultRollback=true)
public class MyServiceTest extends AbstractJUnit38SpringContextTests  {
    @Autowired
    private MyService myService;

    @BeforeClass
    public static void setUpClass() throws Exception {
    }

    @AfterClass
    public static void tearDownClass() throws Exception {
    }

    @Test
    public void testInsert(){
        long id = myService.addPerson( "JUNIT" );
        assertNotNull( id );
        if( id < 1 ){
            fail();
        }
    }
}
_

問題は、トランザクションがロールバックされたためにこのテストが失敗することですが、挿入は問題ありません! @TransactionConfiguration(defaultRollback=true)を削除すると、テストはパスしますが、新しいレコードがデータベースに挿入されます。

_@Test
@Transactional
@Rollback(true)
public void testInsert(){
    long id = myService.addPerson( "JUNIT" );
assertNotNull(id);
if( id < 1 ){
        fail();
    }
}
_

パスを正しくテストできるようになりましたが、ロールバックは無視され、レコードがデータベースに挿入されます。 myService内のメソッドaddPerson()に_@Transactional_の注釈を付けました。ロールバックが無視されるのはなぜですか?

36
blow

トランザクション境界をテストメソッドの境界まで拡張する必要があります。それには、テストメソッド(またはテストクラス全体)に@Transactional

@Test 
@Transactional
public void testInsert(){ 
    long id=myService.addPerson("JUNIT"); 
    assertNotNull(id); 
    if(id<1){ 
        fail(); 
    } 
} 

このアプローチを使用して、ロールバック前にデータが正しく書き込まれたことを確認することもできます。

@Autowired SessionFactory sf;

@Test 
@Transactional
public void testInsert(){ 
    myService.addPerson("JUNIT"); 
    sf.getCurrentSession().flush();
    sf.getCurrentSession().doWork( ... check database state ... ); 
} 
30
axtavt

チェックアウト

http://static.springsource.org/spring/docs/2.5.x/reference/testing.html

特にセクション8.3.4

Springには、各テストをトランザクションでラップするテスト用のクラスがいくつかあるため、DBは変更されません。必要に応じて、その機能を変更できます。

編集-より多くの情報に基づいて、あなたは見たいかもしれません

AbstractTransactionalJUnit38SpringContextTests at

http://static.springsource.org/spring/docs/2.5.x/api/org/springframework/test/context/junit38/AbstractTransactionalJUnit38SpringContextTests.html

2
hvgotcodes

クラスの前に次の注釈を使用します。

_@TransactionConfiguration(transactionManager = "txManager",defaultRollback = true)
@Transactional
_

ここでtxManagerは、アプリケーションコンテキストのトランザクションマネージャーです。

ここで、txManagerは、_application context_からのトランザクションマネージャーのインスタンスまたはBean IDです。

_<!-- Transaction Manager -->
    <bean id="txManager"
          class="org.springframework.orm.hibernate3.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory" />
    </bean>

    <tx:annotation-driven transaction-manager="txManager" />
_

setUp()メソッド内にコードを追加します。これは、テストの開始時に実行され、最後にラップアップされるコードは、最後に実行されるteatDown()メソッドに配置する必要があります。または、代わりに_@Before_および_@After_注釈を使用することもできます。

1
user3145373 ツ

もしあなたの

myService.addPerson("JUNIT"); 

メソッドには@Transactionalのように注釈が付けられます。これを修正しようとすると、いくつかの異なる種類またはエラーが発生します。そのため、DAOメソッドをテストするだけの方が良いでしょう。

0
Danylo Volokh