1前書き

Springはリンク:/transaction-configuration-with-jpa-spring[アプリケーションコード]およびリンク:/spring-jpa-test-in-memory-database[統合テスト]を通じて宣言的トランザクション管理をサポートしています。

ただし、トランザクション境界をきめ細かく制御する必要がある場合もあります。

この記事では、トランザクションテストでSpringが設定した自動トランザクションとプログラム的にやり取りする方法を説明します。


2前提条件

Springアプリケーションにいくつかの統合テストがあるとしましょう。

具体的には、データベースとやり取りするテストを検討しています。たとえば、永続層が正しく動作していることを確認します。

トランザクションとしてアノテートされた標準のテストクラスを考えてみましょう。

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = { HibernateConf.class })
@Transactional
public class HibernateBootstrapIntegrationTest { ... }

そのようなテストでは、

すべてのテストメソッドはトランザクションにラップされ、メソッドが終了するとロールバックされます

もちろん、特定のメソッドにのみ注釈を付けることもできます。

この記事で説明することはすべてこのシナリオにも当てはまります。


3

TestTransaction

クラス

この記事の残りの部分では、単一のクラスについて説明します。


org.springframework.test.context.transaction.TestTransaction

これは、テストでトランザクションと対話するために使用できるいくつかの静的メソッドを持つユーティリティクラスです。

各メソッドは、テストメソッドの実行中に設定されている現在の唯一のトランザクションと対話します。


3.1. 現在のトランザクションの状態を確認する

テストでよくすることの1つは、物事が想定される状態にあることを確認することです。

したがって、現在アクティブなトランザクションがあるかどうかを確認したいかもしれません。

assertTrue(TestTransaction.isActive());

または、現在のトランザクションにロールバックのフラグが設定されているかどうかを確認したい場合があります。

assertTrue(TestTransaction.isFlaggedForRollback());

そうであれば、Springは自動的にまたはプログラム的に、それが終了する直前にそれをロールバックします。それ以外の場合は、閉じる直前にコミットします。


3.2. コミットまたはロールバックのためのトランザクションのフラグ付け

トランザクションを閉じる前にコミットまたはロールバックするようにプログラムでポリシーを変更できます。

TestTransaction.flagForCommit();
TestTransaction.flagForRollback();

通常、テスト中のトランザクションは開始時にロールバックのフラグが立てられます。ただし、メソッドに

@ Commit

アノテーションがある場合は、代わりにコミットのフラグが立てられます。

@Test
@Commit
public void testFlagForCommit() {
    assertFalse(TestTransaction.isFlaggedForRollback());
}

それらの名前が意味するように、これらのメソッドは単にトランザクションにフラグを立てることに注意してください。つまり、** トランザクションはすぐにコミットまたはロールバックされるのではなく、終了する直前に限ります。


3.3. トランザクションの開始と終了

トランザクションをコミットまたはロールバックするには、メソッドを終了させるか、明示的に終了させます。

TestTransaction.end();

後でデータベースとやり取りしたい場合は、新しいトランザクションを開始する必要があります。

TestTransaction.start();

メソッドのデフォルトの設定に従って、新しいトランザクションにロールバック(またはコミット)のフラグが立てられます。つまり、以前の

flagFor …​

への呼び出しは新しいトランザクションには影響しません。


4実装の詳細


TestTransaction

は魔法のようなものではありません。 Springでのテストにおけるトランザクションについてもう少し学ぶために、実装について見ていきましょう。

そのいくつかのメソッドは単に現在のトランザクションにアクセスし、その機能の一部をカプセル化していることがわかります。


4.1.

TestTransaction

は現在のトランザクションをどこから取得しますか?

コードに直行しましょう。

TransactionContext transactionContext
  = TransactionContextHolder.getCurrentTransactionContext();


TransactionContextHolder

は、

TransactionContext

を保持する

ThreadLocal

の周りの単なる静的ラッパーです。


4.2. 誰がスレッドローカルコンテキストを設定するのですか?

だれが

setCurrentTransactionContext

メソッドを呼び出すかを見ると、呼び出し元は1つだけです。


TransactionalTestExecutionListener.beforeTestMethod


TransactionalTestExecutionListener

は、@ @ Transactional__のアノテーションが付けられたテストに対してSpringsが自動的に設定するリスナーです。


TransactionContext

は実際のトランザクションへの参照を保持していないことに注意してください。代わりに、それは単に

PlatformTransactionManager

の上のファサードです。

はい、このコードは非常に重層的で抽象的です。これらは、多くの場合、Springフレームワークの中核部分です。

複雑さの下で、Springがどのように黒魔術をしていないのかを見るのは面白いです。


5結論

このクイックチュートリアルでは、Springベースのテストでトランザクションとプログラム的にやり取りする方法を説明しました。

これらすべての例の実装はhttps://github.com/eugenp/tutorials/tree/master/persistence-modules/spring-hibernate-5[the GitHub project]にあります – これはMavenプロジェクトです。そのままインポートして実行するのは簡単です。