스프링 @transactional을 사용한 다중 스레드 테스트 테스트
-
18-09-2019 - |
문제
TestNG를 사용하여 Persistence Spring Modules (JPA+Hibernate)를 기본 클래스로서 AbstractTransactionalTestngspringContextTests를 사용하여 테스트하고 있습니다. 모든 중요한 부분 @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를 확장하고 각 방법 (즉, TransactionTemPlate의 경우)에 따라 (@Transactional Annotation 대신) 프로그래밍 방식으로 트랜잭션을 유지하는 것입니다.
@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
}
}
}
해결책
트랜잭션은 동일한 스레드에서 시작해야합니다. 자세한 내용은 다음과 같습니다.
Spring3/Hibernate3/Testng : 일부 테스트는 LazyInitializationException을 제공하지만 일부는 그렇지 않습니다.
다른 팁
이것이 오히려 org.springframework.test.context.testcontextmanager에서 나오지 않는다고 생각하지 마십시오. https://jira.springsource.org/browse/spr-5863)?
트랜잭션 테스트 테스트를 병렬로 시작하고 싶을 때 같은 문제에 직면했으며 스프링이 실제로 트랜잭션을 올바른 스레드에 바인딩하려고 시도하는 것을 알 수 있습니다.
그러나 이것은 이런 종류의 오류로 무작위로 실패합니다. 나는 acpracttransactionalTestngspringContextTests를 확장했다 :
@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);
}
(키는 동기화 된 것입니다 ...)
그리고 그것은 이제 매력처럼 작동하고 있습니다. 나는 봄 3.2를 기다릴 수 없어 완전히 평행 할 수 있도록!