我試圖讓事務在Grails服務中工作,但我沒有得到我期待的結果。如果我的假設是關閉的,有人可以告訴我我做錯了什麼嗎?Grails服務交易
我的域類:
class Account {
static constraints = {
balance(min: 0.00)
}
String companyName
BigDecimal balance = 0.00
Boolean active = true
String toString() {
return "${companyName} : ${balance}"
}
}
我的服務:
class AccountService {
static transactional = true
def transfer(Account source, Account destination, amount) throws RuntimeException {
if (source.active && destination.active) {
source.balance -= amount
if (!source.save(flush: true)) {
throw new RuntimeException("Could not save source account.")
} else {
destination.balance += amount
if (!destination.save(flush: true)) {
throw new RuntimeException("Could not save destination account.")
}
}
} else {
throw new RuntimeException("Both accounts must be active.")
}
}
def someMethod(Account account) throws RuntimeException {
account.balance = -10.00
println "validated: ${account.validate()}"
if(!account.validate()) {
throw new RuntimeException("Rollback!")
}
}
}
我的單元測試: 進口grails.test *
class AccountServiceTests extends GrailsUnitTestCase {
def AccountService
protected void setUp() {
super.setUp()
mockDomain(Account)
AccountService = new AccountService()
}
protected void tearDown() {
super.tearDown()
}
void testTransactional() {
def account = new Account(companyName: "ACME Toy Company", balance: 2000.00, active: true)
def exception = null
try {
AccountService.someMethod(account)
} catch (RuntimeException e) {
exception = e
}
assert exception instanceof RuntimeException
println "exception thrown: ${exception.getMessage()}"
assertEquals 2000.00, account.balance
}
}
結果:
Testsuite: AccountServiceTests
Tests run: 1, Failures: 1, Errors: 0, Time elapsed: 1.068 sec
------------- Standard Output ---------------
--Output from testTransactional--
validated: false
exception thrown: Rollback!
------------- ---------------- ---------------
------------- Standard Error -----------------
--Output from testTransactional--
------------- ---------------- ---------------
Testcase: testTransactional took 1.066 sec
FAILED
expected:<2000.00> but was:<-10.00>
junit.framework.AssertionFailedError: expected:<2000.00> but was:<-10.00>
at AccountServiceTests.testTransactional(AccountServiceTests.groovy:89)
at _GrailsTest_groovy$_run_closure4.doCall(_GrailsTest_groovy:203)
at _GrailsTest_groovy$_run_closure4.call(_GrailsTest_groovy)
at _GrailsTest_groovy$_run_closure2.doCall(_GrailsTest_groovy:147)
at _GrailsTest_groovy$_run_closure1_closure19.doCall(_GrailsTest_groovy:113)
at _GrailsTest_groovy$_run_closure1.doCall(_GrailsTest_groovy:96)
at TestApp$_run_closure1.doCall(TestApp.groovy:66)
at gant.Gant$_dispatch_closure4.doCall(Gant.groovy:324)
at gant.Gant$_dispatch_closure6.doCall(Gant.groovy:334)
at gant.Gant$_dispatch_closure6.doCall(Gant.groovy)
at gant.Gant.withBuildListeners(Gant.groovy:344)
at gant.Gant.this$2$withBuildListeners(Gant.groovy)
at gant.Gant$this$2$withBuildListeners.callCurrent(Unknown Source)
at gant.Gant.dispatch(Gant.groovy:334)
at gant.Gant.this$2$dispatch(Gant.groovy)
at gant.Gant.invokeMethod(Gant.groovy)
at gant.Gant.processTargets(Gant.groovy:495)
at gant.Gant.processTargets(Gant.groovy:480)
我的期望:
當帳戶被授予負平衡,它不應該驗證(它沒有),一個RuntimeException應甩(它是),並且賬戶應該回滾到之前的狀態(餘額:2000),這是它分崩離析的地方。
我在這裏錯過了什麼?
嘿伯特,完全有道理。唉,仍然沒有運氣。它仍然應該拋出異常,但它並沒有回滾。 – Thody 2010-01-15 18:18:09
現在,它是如何工作的。帳戶實例的數據不會回滾,但更改不會持久。將'def sessionFactory'添加爲依賴注入字段,並在最後一個assertEquals之前添加對'sessionFactory.currentSession.clear()'和'account = Account.get(account.id)'的調用以強制重新加載帳戶實例並且測試會通過。 – 2010-01-16 07:14:48
對於使用它爲交易服務編寫集成測試的人來說,只是一個快速提示。集成測試本身是事務性的,所以你的服務不會在新的事務中。這可能會導致意外的行爲。解決方法是在集成測試中關閉事務(static transactional = false)。 – 2010-03-18 14:22:28