有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

用于spring测试的java JUnit多事务管理器

我正在使用Spring3.0.5和JUnit4.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) 个答案

  1. # 1 楼答案

    查看Spring5 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回滚

  2. # 2 楼答案

    因为Java不允许每个元素有多个相同类型的注释,所以必须找到另一种方法来配置它@TransactionConfiguration^{}解释,其^{}方法仅返回单个PlatformTransactionManager。它查看@Transactional,但似乎忽略了Seam 3.0中添加的value限定符

    @Transactional本身仅支持单个事务管理器。真正的应用程序是如何配置的?您必须使用@Transactional("<qualifier>")(如the docs),对吗

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

    您正在嵌套事务吗?也就是说,在一个方法上有@Transactional(“tm1”),该方法调用了一个嵌套的方法,该方法有@Transactional(“tm2”)?听起来有点不寻常。您可以尝试以同样的方式设置您的测试,使用两个test@服务,每个服务都带有适当的@Transactional注释,它们像往常一样由tx:advice代理。外部服务设置外部txn;内部服务设置内部txn并包含实际测试代码。你不能使用@Rollback,但是嘿,hacks并不漂亮

    另一个选项是创建您自己的平台TransactionManager,将其委托给其他两个经理(仅用于测试目的)

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

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