我正在使用Spring 3.0.5和Junit 4.8.2 是否可以在测试期间使用多个事务管理器?
基本上我会尝试这样的事情。我需要在测试期间从两个单独的数据库中添加和删除内容。
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:/applicationContext-test.xml" })
@TransactionConfiguration(transactionManager = "txMgrA", defaultRollback = true)
@TransactionConfiguration(transactionManager = "txMgrB", defaultRollback = true)
@Transactional
public class SampleTest {
...
}
答案 0 :(得分:4)
由于Java不允许每个元素使用相同类型的多个注释,因此必须找到另一种配置方法。 @TransactionConfiguration
由TransactionalTestExecutionListener
解释,其getTransactionManager
方法仅返回单个PlatformTransactionManager。它查看@Transactional但似乎忽略了Seam 3.0中添加的value
限定符。
@Transactional本身仅支持单个事务管理器。如何配置真正的应用程序?您必须使用@Transactional("<qualifier>")
(如the docs中所示),对吧?
如果你只是在不同的方法上使用@Transactional与不同的tx管理器,那么最简单的解决方案是分割你的测试类。
您是否正在嵌套交易?也就是说,你在一个方法上有@Transactional(“tm1”),它调用一个具有@Transactional(“tm2”)的嵌套方法?听起来有点不寻常。您可以尝试以相同的方式设置测试 - 有两个测试@Services,每个都有相应的@Transactional注释,像往常一样用tx:advice代理。外部服务设置外部txn;内部服务设置内部txn并包含实际的测试代码。你不能使用@Rollback,但嘿,黑客并不漂亮。
另一个选择是创建自己的PlatformTransactionManager,委托给另外两个管理器(仅用于测试目的)。
也许更好的方法是放弃并手动管理测试的@ Before / @ After方法中的两个事务。
最好是使用JTA全局事务。希望你实际上并没有嵌套单独的交易,这一切都没有实际意义;)
答案 1 :(得分:1)
看一下Spring 5 TransactionalTestExecutionListener
的实现,它似乎仅支持一个TransactionManager
每个线程 ,这似乎是该侦听器的设计缺陷,可能与您在2011年遇到过:)
但是,目前可以使用ChainedTransactionManager
解决此问题。如果您有多个事务管理器,则可以在测试上下文中定义另一个事务管理器:
@Configuration
class TestTransactionConfig {
@Bean("testTransactionManager")
public PlatformTransactionManager chainedTransactionManager(
@Qualifier("transactionManager1") PlatformTransactionManager transactionManager1,
@Qualifier("transactionManager2") PlatformTransactionManager transactionManager2
) {
return new ChainedTransactionManager(transactionManager1, transactionManager2);
}
}
现在,您可以使用此事务管理器定义测试的基类:
@RunWith(SpringRunner::class)
@Transactional("testTransactionManager")
class BaseTransactionalTest {
}
对于所有派生类,所有测试方法现在都将包含在两个事务中,最终将由TransactionalTestExecutionListener
回滚。