代码之家  ›  专栏  ›  技术社区  ›  Gennady Shumakher

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

  •  3
  • Gennady Shumakher  · 技术社区  · 16 年前

    当我试图在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 annotation)为每个方法维护事务(即使用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
            }
        }
    }
    
    2 回复  |  直到 16 年前
        2
  •  2
  •   Such    14 年前

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

    当我想并行启动事务性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);
    }
    

    现在它就像一个符咒。我已经等不及Spring3.2了,这样它就可以完全并行化了!