如何测试事务数据库代码?
How can you test transactional database code?
假设您有一些简单的代码,您可以在一个事务中向数据库中插入两行。
如何让第二个在测试中失败以检查第一个是否回滚?
会不会是一个webservice,我会通过元编程来模拟它,以便让第二次调用失败。
但是对于数据库代码我不确定。是否可能有某种 jdbc 驱动程序每 7 次操作抛出异常(比方说)?
好的,让我们更具体一点:
假设您有一些遗留代码。它的结构不是很好,但您也不想重构它(让我们先写一些测试!)。事务行为似乎有问题,您想测试您的代码。
由于代码基本可以工作,因此很难使部分代码因违反约束而失败。
所以我想在我的测试中做的是模拟如果数据库失败(可能是因为存在死锁、不可用、磁盘已满或类似情况)或当您 "pull the plug" 时会发生什么。
集成测试是测试事务和回滚的合适场所。像这样的示例就足够了:
package com.example
import grails.test.mixin.integration.Integration
import grails.transaction.*
import spock.lang.*
import org.springframework.beans.factory.annotation.Autowired
@Integration
@Rollback
class TransactionIntSpec extends Specification {
@Autowired
FooService service
void "test transaction rollback"() {
given: 'bar service throws exception'
service = Mock(FooService) {
serviceBar() >> { throw new Exception() }
}
when:
service.serviceMethod()
then:
!Foo.count() && !Bar.count()
}
void "test transaction successfull"() {
when:
service.serviceMethod()
then:
Foo.count() && Bar.count()
}
}
其中 Foo
和 Bar
只是简单的域 classes,服务 class 看起来像:
package com.example
import grails.transaction.Transactional
@Transactional
class FooService {
def serviceMethod() {
serviceFoo()
serviceBar()
}
def serviceFoo() {
new Foo().save(flush: true, failOnError: true)
}
def serviceBar() {
new Bar().save(flush: true, failOnError: true)
}
}
在 Grails 3.0.2 中测试
假设您有一些简单的代码,您可以在一个事务中向数据库中插入两行。
如何让第二个在测试中失败以检查第一个是否回滚?
会不会是一个webservice,我会通过元编程来模拟它,以便让第二次调用失败。
但是对于数据库代码我不确定。是否可能有某种 jdbc 驱动程序每 7 次操作抛出异常(比方说)?
好的,让我们更具体一点:
假设您有一些遗留代码。它的结构不是很好,但您也不想重构它(让我们先写一些测试!)。事务行为似乎有问题,您想测试您的代码。
由于代码基本可以工作,因此很难使部分代码因违反约束而失败。
所以我想在我的测试中做的是模拟如果数据库失败(可能是因为存在死锁、不可用、磁盘已满或类似情况)或当您 "pull the plug" 时会发生什么。
集成测试是测试事务和回滚的合适场所。像这样的示例就足够了:
package com.example
import grails.test.mixin.integration.Integration
import grails.transaction.*
import spock.lang.*
import org.springframework.beans.factory.annotation.Autowired
@Integration
@Rollback
class TransactionIntSpec extends Specification {
@Autowired
FooService service
void "test transaction rollback"() {
given: 'bar service throws exception'
service = Mock(FooService) {
serviceBar() >> { throw new Exception() }
}
when:
service.serviceMethod()
then:
!Foo.count() && !Bar.count()
}
void "test transaction successfull"() {
when:
service.serviceMethod()
then:
Foo.count() && Bar.count()
}
}
其中 Foo
和 Bar
只是简单的域 classes,服务 class 看起来像:
package com.example
import grails.transaction.Transactional
@Transactional
class FooService {
def serviceMethod() {
serviceFoo()
serviceBar()
}
def serviceFoo() {
new Foo().save(flush: true, failOnError: true)
}
def serviceBar() {
new Bar().save(flush: true, failOnError: true)
}
}
在 Grails 3.0.2 中测试