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

时间:2011-06-24 06:42:59

标签: java spring java-ee junit

我正在使用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 {
    ...
}

2 个答案:

答案 0 :(得分:4)

由于Java不允许每个元素使用相同类型的多个注释,因此必须找到另一种配置方法。 @TransactionConfigurationTransactionalTestExecutionListener解释,其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回滚。