简体   繁体   English

使用Spring @Transactional进行TestNG多线程测试

[英]TestNG multithreaded test with Spring @Transactional

I am using TestNG to test persistence Spring modules (JPA+Hibernate) using AbstractTransactionalTestNGSpringContextTests as a base class. 我正在使用TestNG来测试使用AbstractTransactionalTestNGSpringContextTests作为基类的持久性Spring模块(JPA + Hibernate)。 All important parts @Autowired, @TransactionConfiguration, @Transactional work just fine. 所有重要的部分@Autowired,@ TransactionConfiguration,@ Transaction都可以正常工作。

The problem comes when I am trying to run test in parallel threads with threadPoolSize=x, invocationCount=y TestNG annotation. 当我尝试使用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)

... Has anybody faced this problem? ......有人遇到过这个问题吗?

Here is the code: 这是代码:

@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);
    ...
}
...

Update: It seems that AbstractTransactionalTestNGSpringContextTests maintains transaction only for main thread when all other test threads don't get their own transaction instance. 更新:当所有其他测试线程没有获得自己的事务实例时,似乎AbstractTransactionalTestNGSpringContextTests仅为主线程维护事务。 The only way to solve that is to extend AbstractTestNGSpringContextTests and maintain transaction programmatically (instead of @Transactional annotation) per each method (ie with TransactionTemplate): 解决这个问题的唯一方法是扩展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
        }
    }
}

The transaction needs to be started in the same thread, here are more details: 该事务需要在同一个线程中启动,这里有更多细节:

Spring3/Hibernate3/TestNG: some tests give LazyInitializationException, some don't Spring3 / Hibernate3 / TestNG:一些测试给出了LazyInitializationException,有些则没有

Don't you think this rather comes from org.springframework.test.context.TestContextManager not being thread safe (see https://jira.springsource.org/browse/SPR-5863 )? 难道你不认为这是来自org.springframework.test.context.TestContextManager不是线程安全的(参见https://jira.springsource.org/browse/SPR-5863 )?

I faced the same issue when I wanted to launch my Transactional TestNG tests in parallel and you can see that Spring actually tries to bind the transaction to the right Thread. 当我想并行启动Transactional TestNG测试时,我遇到了同样的问题,你可以看到Spring实际上试图将事务绑定到正确的Thread。

However this fails randomly with this kind of errors. 然而,这种错误随机失败。 I extended AbstractTransactionalTestNGSpringContextTests with : 我扩展了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);
}

(the key being the synchronized...) (关键是同步......)

and it is now working like a charm. 它现在像一个魅力。 I can't wait for Spring 3.2 though so that it can be completly parallized! 我不能等到Spring 3.2,所以它可以完全平行!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM