Я пытаюсь заставить транзакции работать в сервисе 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) , где он разваливается.
Что мне здесь не хватает?