嵌套的內部事務已經提交的數據更改實際上應該在父事務中立即可見。
我真的不知道他們爲什麼是而不是在GroovyTestCase
的事務上下文中。 Others don't know, as well, and are using similar approaches to mine。
考慮下面的測試用例。測試用例本身是而不是事務性,但調用事務性方法。 - 這符合預期。
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()
getter。
謝謝,所以看起來這是一個集成測試框架的錯誤。即代碼/邏輯是否正確,並在正在運行的應用程序中工作,但不在集成測試中?也許我應該JIRA它 – Sunny 2010-11-12 06:00:45
我不認爲這是一個錯誤(這個問題太重要了/突出),而是一個設計缺陷。 - 如果您應該提交JIRA問題(使用Spring而不是Grails框架),請在此處留言。 – robbbert 2010-11-12 12:30:10
對最後一個示例(過時?)的更正:'Propagation.REQUIRES_NEW'開始一個新的_unrelated和independent_事務。相比之下,'Propagation.NESTED'下出現_nested_事務(對父對象和其自己的保存點可見)。 Spring Javadoc做了很好的解釋差異:http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/transaction/annotation/Propagation.html – 2015-02-05 14:45:00