3

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

2 回答 2

2

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

Spring3/Hibernate3/TestNG:有些测试给出 LazyInitializationException,有些则没有

于 2010-02-05T04:10:08.727 回答
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 以便它可以完全并行化!

于 2012-01-05T11:07:03.970 回答