2010-02-04 98 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的完全并行化!