我想集成测试一个调用使用@Transactional(propagation = Propagation.REQUIRES_NEW)
的方法的服务方法。但是,基于内部(新)事务的断言失败。
class MyService {
@Transactional(propagation = Propagation.NESTED)
def method1() {
method2()
}
@Transactional(propagation = Propagation.REQUIRES_NEW)
def method2() {
// some code that will modify the DB
}
}
class MyServiceNonTransactionalIntegrationSpec extends IntegrationSpec {
static transactional = false
def myService = new MyService()
setup() {
// populate database here
}
cleanup() {
// teardown database here after tests complete
}
def method1() {
when: "we test the main method"
myService.method1()
then: "we should be able to see the result of method 1 and method 2"
// BUT: (!!!)
// assertions based on state of database fail, perhaps because new transaction
// wrapped around method 2 has not yet committed
}
}
如何集成测试method1()
?
编辑:
为了解决代理问题,我尝试了以下方法,但仍然无法让它工作:
class MyService {
def myService2
@Transactional(propagation = Propagation.NESTED)
def method1() {
myService2.method2()
}
}
class MyService2 {
@Transactional(propagation = Propagation.REQUIRES_NEW)
def method2() {
// some code that will modify the DB
}
}
class MyServiceNonTransactionalIntegrationSpec extends IntegrationSpec {
static transactional = false
def myService = new MyService()
def myService2 = new MyService2()
setup() {
myService.myService2 = myService2
// populate database here
}
// rest as before
}
答案 0 :(得分:1)
如果您正在使用org.springframework.transaction.annotation.Transactional
,这只是一个自我调用的问题 - 您应该使用@grails.transaction.Transactional
而不是具有相同的配置选项但使用AST转换而不是运行时代理来避免问题不调用代理方法。使用Grails注释时,会重写每个方法以模拟为每个方法创建代理,将代码包装在基于该方法的注释设置配置的事务模板中(在方法上显式,或从类范围注释推断) )。
但您的测试已被破坏,因为您正在使用new
来创建服务。 始终在集成测试中使用依赖注入,因此您可以获得已配置的Spring bean,而不仅仅是新的未初始化的POGO。为此,请添加与测试之外相同的属性语法:
def myService
def myService2
并删除Spring为您执行的不必要的布线代码(例如myService.myService2 = myService2
)。
答案 1 :(得分:0)
你面临着自我调用。点击此处:Spring - @Transactional - What happens in background?或Spring @Transactional Annotation : Self Invocation
以下是我的一个课程的摘录:
@Service("authzService")
public class AuthorizationService implements IAuthorizationService {
@Resource(name="authzService")
private IAuthorizationService self;
我使用这个私有成员来自行调用带有@Cached注释的方法。