【问题标题】:TestNG multithreaded test with Spring @Transactional使用 Spring @Transactional 进行 TestNG 多线程测试
【发布时间】:2012-01-05 19:07:03
【问题描述】:

我正在使用 TestNG 以 AbstractTransactionalTestNGSpringContextTests 作为基类来测试持久性 Spring 模块(JPA+Hibernate)。 @Autowired、@TransactionConfiguration、@Transactional 的所有重要部分都可以正常工作。

当我尝试使用 threadPoolSize=x, invocationCount=y TestNG 注释在并行线程中运行测试时出现问题。

WARNING: Caught exception while allowing TestExecutionListener [org.springframework.test.context.transaction.TransactionalTestExecutionListener@174202a] 
to process 'before' execution of test method [testCreate()] for test instance [DaoTest] java.lang.IllegalStateException:
Cannot start new transaction without ending existing transaction: Invoke endTransaction() before startNewTransaction().
at org.springframework.test.context.transaction.TransactionalTestExecutionListener.beforeTestMethod(TransactionalTestExecutionListener.java:123)
at org.springframework.test.context.TestContextManager.beforeTestMethod(TestContextManager.java:374)
at org.springframework.test.context.testng.AbstractTestNGSpringContextTests.springTestContextBeforeTestMethod(AbstractTestNGSpringContextTests.java:146)

... 有人遇到过这个问题吗?

代码如下:

@TransactionConfiguration(defaultRollback = false)
@ContextConfiguration(locations = { "/META-INF/app.xml" })
public class DaoTest extends AbstractTransactionalTestNGSpringContextTests {

@Autowired
private DaoMgr dm;

@Test(threadPoolSize=5, invocationCount=10)
public void testCreate() {
    ...
    dao.persist(o);
    ...
}
...

更新: 似乎 AbstractTransactionalTestNGSpringContextTests 在所有其他测试线程都没有获得自己的事务实例时只为主线程维护事务。解决这个问题的唯一方法是扩展 AbstractTestNGSpringContextTests 并以编程方式维护事务(而不是 @Transactional 注释)每个方法(即使用 TransactionTemplate):

@Test(threadPoolSize=5, invocationCount=10)
public void testMethod() {
    new TransactionTemplate(txManager).execute(new TransactionCallbackWithoutResult() {
        @Override
        protected void doInTransactionWithoutResult(TransactionStatus status) {
            // transactional test logic goes here
        }
    }
}

【问题讨论】:

  • 为了好奇-尝试在原型范围内定义您的DaoMgr,看看结果是否相同
  • 注解 DaoMgr 无效。但是AbstractTransactionalTestNGSpringContextTests是用@Transactional注解的,所以所有的测试方法都会在daoMgr被访问之前启动事务。

标签: java multithreading unit-testing spring testng


【解决方案1】:

事务需要在同一个线程中启动,这里有更多细节:

Spring3/Hibernate3/TestNG: some tests give LazyInitializationException, some don't

【讨论】:

    【解决方案2】:

    您不认为这是因为 org.springframework.test.context.TestContextManager 不是线程安全的(请参阅https://jira.springsource.org/browse/SPR-5863)?

    当我想并行启动 Transactional TestNG 测试时,我遇到了同样的问题,您可以看到 Spring 实际上尝试将事务绑定到正确的线程。

    但是,这种错误会随机失败。我扩展了 AbstractTransactionalTestNGSpringContextTests :

    @Override
    @BeforeMethod(alwaysRun = true)
    protected synchronized void springTestContextBeforeTestMethod(
            Method testMethod) throws Exception {
        super.springTestContextBeforeTestMethod(testMethod);
    }
    
    @Override
    @AfterMethod(alwaysRun = true)
    protected synchronized void springTestContextAfterTestMethod(
            Method testMethod) throws Exception {
        super.springTestContextAfterTestMethod(testMethod);
    }
    

    (正在同步的键...)

    它现在就像一个魅力。不过我等不及 Spring 3.2 了,这样它就可以完全并行化了!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-01-02
      • 1970-01-01
      • 2013-09-04
      • 1970-01-01
      • 1970-01-01
      • 2015-09-27
      相关资源
      最近更新 更多