2010-02-04 90 views
3

我使用TestNG來測試使用AbstractTransactionalTestNGSpringContextTests作爲基類的持久性Spring模塊(JPA + Hibernate)。所有重要的部分@Autowired,@TransactionConfiguration,@Transactional工作得很好。TestNG多線程測試Spring @Transactional

當我嘗試在threadPoolSize = x,invocationCount = y TestNG註釋的並行線程中運行測試時,問題出現了。

WARNING: Caught exception while allowing TestExecutionListener [org.springframew[email protected]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只對主線程在所有其他線程測試沒有得到他們自己的事務實例維護交易。解決的唯一途徑是按每個方法(使用TransactionTemplate的IE)編程繼承AbstractTestNGSpringContextTests和維持交易(而不是@Transactional註釋):

@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 
     } 
    } 
} 
+0

爲了好奇 - 嘗試在原型範圍內定義您的「DaoMgr」並查看結果是否相同 – Bozho 2010-02-04 19:50:39

+0

註釋DaoMgr沒有效果。但AbstractTransactionalTestNGSpringContextTests是用@Transactional註釋的,所以所有的測試方法在訪問daoMgr之前啓動事務。 – 2010-02-04 20:24:24

回答

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的完全並行化!