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


86

まず第一に、私はこれについて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を使用しています


ロールバックとはどういう意味ですか?データベースをクリーンアップしますか?
Gaurav 2012

5
実行後とまったく同じ状態に設定する initTest
Jan Vorcak 2012

回答:


129

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

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

デフォルトでは、春には、あなたの試験方法を取り巻く新しいトランザクションを開始します@Before/@Afterコールバック、最後に背中をロール。デフォルトで機能します。コンテキスト内にトランザクションマネージャーがあれば十分です。

差出人:10.3.5.4トランザクション管理(太字の鉱山):

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


2
さて、私は以前にこれを試しましたが、それでも機能しません、多分...問題は私がPlatformTransactionManagerを定義しなかったことである可能性があります、どうすればそれを行うことができますか?
Jan Vorcak 2012

@javo:データベースをどのように変更していますか?Jpa / Hibernate / JdbcTemplate / ...を使用している場合は、いくつかある必要がありますPlatformTransactionManager。それ以外の場合、Springはトランザクションとデータベースについてどのように認識しますか?
Tomasz Nurkiewicz 2012

1
この回答のリンクは正しくありません。Springのドキュメントからの正しいリンクと詳細なコンテキストについては、以下のuser2418306の回答を参照してください。
DaveyDaveDave 2016年

1
私は機能しません。各メソッドには個別のトランザクションが必要です。クラス全体でそれを行うことはできません
Kamil Nekanowicz 2018

テーブルへの挿入をテストしています。@Transactionalを使用すると、挿入コマンドはデータベースに対しても発行されません(コンソールに休止状態のshow-sql trueがあるため、これを確認できます)。多くの場合、正常に動作します。しかし、私のテストの1つは、データベースの制約のためにデータベースがDataAccessExceptionを発行することを確認します。この場合、ロールバックが「メモリ内」で発生し、データベースが呼び出されないため、テストは失敗します。解決策:クラスレベルではなく@Transactional@Testメソッドレベルで使用します。
PauloMerson18年

17

余談ですが、 Tomasz Nurkiewiczの回答を修正する試みは拒否されました:

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


統合テストに関するドキュメントの関連セクションへの正確で永続的なリンク

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

@Configuration
@PropertySource( "application.properties")
パブリッククラスの永続性{
    @Autowired
    環境環境;

    @豆
    DataSource dataSource(){
        新しいDriverManagerDataSource(を返します
                env.getProperty( "datasource.url")、
                env.getProperty( "datasource.user")、
                env.getProperty( "datasource.password")
        );
    }

    @豆
    PlatformTransactionManager transactionManager(){
        新しいDataSourceTransactionManager(dataSource());を返します。
    }
}

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

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {Persistence.class、SomeRepository.class})
@Transactional
パブリッククラスSomeRepositoryTest {...}

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


12

追加について言及して@Transactionalいる答えは正しいですが、簡単にするために、テストクラスを設定することもできますextends AbstractTransactionalJUnit4SpringContextTests


1
クラスレベルでのアノテーション「@Transactional」の追加は機能せず、関数ごとに個別にアノテーション「@Transactional」を追加することは機能し、AbstractTransactionalJUnit4SpringContextTestsも機能します
KamilNekanowicz18年

5

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

私のテストクラス

@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" />

それが役に立てば幸い。


さて、あなたはあなたのステートメントを手動でコミットしますか?あなたのデータがあなたのデータベースにさえ書かれたと確信していますか?
franta kocourek 2017年

Spring Transactionsを理解するのに苦労している人は、データソースが自動コミットに設定されていないことを確認してください。そうしないと、@ Transactionalが何もしないように見える理由を理解しようと夢中になります。
ジョー・エルンスト

2

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

@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
     }
}

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


0

メソッドの追加に加え@Transactional@Test、追加する必要もあります@Rollback(false)


-5

ロールバックを無効にすることができます:

@TransactionConfiguration(defaultRollback = false)

例:

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = Application.class)
@Transactional
@TransactionConfiguration(defaultRollback = false)
public class Test {
    @PersistenceContext
    private EntityManager em;

    @org.junit.Test
    public void menge() {
        PersistentObject object = new PersistentObject();
        em.persist(object);
        em.flush();
    }
}

6
これは、OPが求めているものとは正反対です
Adam Michalik 2016年

これは、受け入れられた回答へのコメントであるはずです。
DerMike 2018年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.