web-dev-qa-db-ja.com

@Testの後のトランザクションのロールバック

まず、これについてStackOverflowで多くのスレッドを見つけましたが、それらのどれも本当に私を助けませんでした。

Spring-testを使用してJUnitテストを実行しています。コードは次のようになります

@RunWith(SpringJUnit4ClassRunner.class)  
@ContextConfiguration(locations = {})
public class StudentSystemTest {

    @Autowired
    private StudentSystem studentSystem;

    @Before
    public void initTest() {
    // set up the database, create basic structure for testing
    }

    @Test
    public void test1() {
    }    
    ...  
}

私の問題は、テストが他のテストに影響を与えないようにすることです。そこで、各テストのロールバックのようなものを作成したいと思います。私はこれを多く検索しましたが、これまでのところ何も見つかりませんでした。このためにHibernateとMySqlを使用しています

65
Jan Vorcak

テストの上に@Transactional注釈を追加するだけです:

@RunWith(SpringJUnit4ClassRunner.class)  
@ContextConfiguration(locations = {"testContext.xml"})
@Transactional
public class StudentSystemTest {

デフォルトでは、Springはテストメソッドと@Before/@Afterコールバックを取り巻く新しいトランザクションを開始し、最後にロールバックします。デフォルトで機能します。コンテキストにトランザクションマネージャがあれば十分です。

From: 10.3.5.4 Transaction management (bold mine):

TestContextフレームワークでは、トランザクションはTransactionalTestExecutionListenerによって管理されます。テストクラスで@TestExecutionListenersを明示的に宣言していなくても、TransactionalTestExecutionListenerはデフォルトで構成されていることに注意してください。ただし、トランザクションのサポートを有効にするには、@ContextConfigurationセマンティクスによってロードされるアプリケーションコンテキストでPlatformTransactionManager Beanを提供する必要があります。また、テストのクラスまたはメソッドレベルで@Transactionalを宣言する必要があります

110

脇:Tomasz Nurkiewiczの答えを修正する試みは拒否されました:

この編集では、投稿が少しでも読みやすく、見つけやすく、より正確に、またはアクセスしやすくなりません。変更は完全に不要であるか、積極的に可読性を損ないます。


正しく永続的 link 統合テストに関するドキュメントの関連セクションへ。

トランザクションのサポートを有効にするには、@ContextConfigurationセマンティクスを介してロードされるPlatformTransactionManagerApplicationContext Beanを構成する必要があります。

 @ Configuration 
 @ PropertySource( "application.properties")
 public class Persistence {
 @Autowired 
 Environment env; 
 
 @Bean 
 DataSource dataSource(){
 return新しいDriverManagerDataSource(
 env.getProperty( "datasource.url")、
 env.getProperty ( "datasource.user")、
 env.getProperty( "datasource.password")
); 
} 
 
 @Bean 
 PlatformTransactionManager transactionManager(){
 return DataSourceTransactionManager(dataSource()); 
} 
} 

さらに、テストのクラスレベルまたはメソッドレベルでSpringの@Transactionalアノテーションを宣言する必要があります。

 @ RunWith(SpringJUnit4ClassRunner.class)
 @ ContextConfiguration(classes = {Persistence.class、SomeRepository.class})
 @ Transactional 
 public class SomeRepositoryTest {.. 。} 

テストメソッドに@Transactionalアノテーションを付けると、テストはトランザクション内で実行され、デフォルトでは、テストの完了後に自動的にロールバックされます。テストクラスに@Transactionalアノテーションが付けられている場合、そのクラス階層内の各テストメソッドはトランザクション内で実行されます。

15
user2418306

@Transactionalの追加に関する回答は正しいですが、簡単にするために、テストクラスextends AbstractTransactionalJUnit4SpringContextTestsを使用することもできます。

11
matt b

答えを投稿するのは遅すぎますが、誰かの助けになることを期待しています。さらに、テストでこの問題を解決しました。これは私が私のテストで持っていたものです:

私のテストクラス

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "path-to-context" })
@Transactional
public class MyIntegrationTest 

コンテキストXML

<bean id="dataSource" class="org.Apache.commons.dbcp.BasicDataSource">
   <property name="driverClassName" value="${jdbc.driverClassName}" />
   <property name="url" value="${jdbc.url}" />
   <property name="username" value="${jdbc.username}" />
   <property name="password" value="${jdbc.password}" />
</bean>

データベースが自動的にクリーンアップされないという問題がまだありました。

BasicDataSourceに次のプロパティを追加すると問題は解決しました

<property name="defaultAutoCommit" value="false" />

それが役に立てば幸い。

4
Atul Kumbhar

スプリントコンテキストとトランザクションマネージャーを使用してテストを実行する必要があります。

@RunWith(SpringJUnit4ClassRunner.class)  
@ContextConfiguration(locations = {"/your-applicationContext.xml"})
@TransactionConfiguration(transactionManager="txMgr")
public class StudentSystemTest {

     @Test
     public void testTransactionalService() {
         // test transactional service
     }

     @Test
     @Transactional
     public void testNonTransactionalService() {
         // test non-transactional service
     }
}

詳細については、Springリファレンスの 10. Testing の章を参照してください。

0
Johan Sjöberg