JUnit用于弹簧测试的多个事务管理器

Cro*_*ias 5 java junit spring java-ee

我正在使用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 {
    ...
}
Run Code Online (Sandbox Code Playgroud)

Luk*_*ski 6

看看 Spring 5TransactionalTestExecutionListener的实现,它看起来只支持TransactionManager 每个线程一个,这似乎是这个监听器的一个设计缺陷,可能和你在 2011 年遇到的一样:)

但是,目前可以使用 来解决此问题ChainedTransactionManager。如果您有多个事务管理器,您可以在测试上下文中定义另一个事务管理器:

@Configuration
class TestTransactionConfig {

    @Bean("testTransactionManager")
    public PlatformTransactionManager chainedTransactionManager(
        @Qualifier("transactionManager1") PlatformTransactionManager transactionManager1,
        @Qualifier("transactionManager2") PlatformTransactionManager transactionManager2
    ) {
        return new ChainedTransactionManager(transactionManager1, transactionManager2);
    }

}
Run Code Online (Sandbox Code Playgroud)

现在,您可以使用此事务管理器定义用于测试的基类:

@RunWith(SpringRunner::class)
@Transactional("testTransactionManager")
class BaseTransactionalTest {

}
Run Code Online (Sandbox Code Playgroud)

对于所有派生类,所有测试方法现在都将包装在两个事务中,最终将由TransactionalTestExecutionListener.


Pet*_*vis 5

由于 Java 不允许每个元素有多个相同类型的注释,因此您必须找到另一种方法来配置它。 @TransactionConfiguration由 解释TransactionalTestExecutionListener,其 getTransactionManager方法仅返回单个 PlatformTransactionManager。它查看 @Transactional 但似乎忽略了valueSeam 3.0 中添加的限定符。

@Transactional 本身只支持单个事务管理器。真实的应用程序是如何配置的?您一定正在使用@Transactional("<qualifier>")(如文档中所示),对吗?

如果您只是在不同的方法上使用 @Transactional 和不同的 tx 管理器,那么最简单的解决方案就是拆分您的测试类。

您是否嵌套事务?也就是说,您在一个方法上有 @Transactional("tm1"),该方法调用具有 @Transactional("tm2") 的嵌套方法?听起来有点不寻常。您可以尝试以相同的方式设置测试 - 有两个测试 @Service,每个都有适当的 @Transactional 注释,并像往常一样使用 tx:advice 进行代理。外部服务设置外部txn;内部服务设置内部 txn 并包含实际的测试代码。你不能使用@Rollback,但是嘿,黑客并不漂亮。

另一种选择是创建您自己的 PlatformTransactionManager 并将其委托给其他两个管理器(仅用于测试目的)。

也许更好的办法是放弃并手动管理测试的 @Before/@After 方法中的两个事务。

最好是使用 JTA 全局事务。希望您实际上并没有嵌套单独的事务,这都是没有意义的;)