ネストされた内部トランザクションがコミットしたデータ変更は、親トランザクションで即座に表示されるはずです。
そして、なぜそれらがa のトランザクションコンテキストにないのか、私には本当にわかりませんGroovyTestCase
。他の人も同様に知りませんが、私のものと同様のアプローチを使用しています。
次のテスト ケースを検討してください。テスト ケース自体はトランザクションではありませんが、トランザクション メソッドを呼び出します。- これは期待どおりに機能します。
class TransactionalMethodTest extends GroovyTestCase {
static transactional = false // test case is not transactional
def customerService
void testTransactionsCommit() {
// start a new transaction,
// setting order 1 inactive
setOrderInactive()
assert ! Order.get(1).isActive
}
@Transactional(propagation = Propagation.REQUIRED)
private void setOrderInactive() {
// make sure that order 1 is active
Order order = Order.get(1)
order.isActive = true
order.save(flush:true)
assert Order.get(1).isActive
// the following method acts in isolation level
// Propagation.REQUIRES_NEW, which means,
// a new, nested, transaction is started
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
customerService.cancelOrders([1])
// changes from the nested transaction are
// visible, instantly
assert ! Order.get(1).isActive
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
}
}
ここで、次の「通常の」トランザクション テスト ケースを考えてみましょう。ネストされたトランザクション内からのデータ変更は、親トランザクションには表示されません。
私が言えることは、トランザクション テスト ケースはネストされたトランザクションでは機能しないため、上記の非トランザクション テスト ケースを使用することです。
原因がわからない場合でも、少なくとも選択肢はわかります。
class TransactionalTestCaseTests extends GroovyTestCase {
static transactional = true // default; Propagation.REQUIRED
def customerService
void testTransactionsCommit() {
// make sure that order 1 is active
Order order = Order.get(1)
order.isActive = true
order.save(flush:true)
assert Order.get(1).isActive
// the following method acts in isolation level
// Propagation.REQUIRES_NEW, which means,
// a new, nested, transaction is started
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
customerService.cancelOrders([1])
// the changes from the inner transaction
// are not yet visible
assert Order.get(1).isActive
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
}
@Override
protected void tearDown() throws Exception {
// the changes from the inner transaction
// are still not visible
assert Order.get(1).isActive
super.tearDown();
}
}
主な質問とは関係ありませんが、全体的な意図に関連して、ネストされたトランザクションが適切にロールバックされているかどうかを確認するテスト ケースを次に示します。
class NestedTransactionRolledBackTests extends GroovyTestCase {
static transactional = false // test case is not transactional
def customerService
void testTransactionsCommit() {
// start a new transaction,
// setting order 1 active
setOrderActive()
assert Order.get(1).isActive
}
@Transactional(propagation = Propagation.REQUIRED)
private void setOrderActive() {
// make sure that order 1 is active
Order order = Order.get(1)
order.isActive = true
order.save(flush:true)
assert Order.get(1).isActive
// the following method acts in isolation level
// Propagation.REQUIRES_NEW, which means,
// a new, nested, transaction is started.
// This transaction will fail, and be rolled back.
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
shouldFail(NullPointerException) {
customerService.cancelOrders([1, -999])
}
// changes from the nested transaction are
// visible, instantly.
// The changes have been rolled back
assert Order.get(1).isActive
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
}
}
. _ boolean transactional = true
_ static transactional = true
後者のモック機能は必要ないため、統合テストもextend
GroovyTestCase
そのサブクラスではなく にする必要があります。フィールドには次のように名前を付ける必要がありますGrailsUnitTestCase
。ゲッターは命名規則によって自動的に生成されます。isActive
active
isActive()