복붙노트

[SPRING] Spring @Transactional을 사용한 TestNG 다중 스레드 테스트

SPRING

Spring @Transactional을 사용한 TestNG 다중 스레드 테스트

TestNG를 사용하여 AbstractTransactionalTestNGSpringContextTests를 기본 클래스로 사용하여 지속성 스프링 모듈 (JPA + 최대 절전 모드)을 테스트하고 있습니다. 모든 중요한 부분 @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 주석 대신 프로그래밍 방식으로 트랜잭션을 유지 관리하는 것입니다.

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

해결법

  1. ==============================

    1.트랜잭션은 동일한 스레드에서 시작해야합니다. 자세한 내용은 다음과 같습니다.

    트랜잭션은 동일한 스레드에서 시작해야합니다. 자세한 내용은 다음과 같습니다.

    Spring3 / Hibernate3 / TestNG : 일부 테스트는 LazyInitializationException을 제공하지만 일부 테스트에서는 그렇지 않습니다.

  2. ==============================

    2.이것은 오히려 org.springframework.test.context.TestContextManager가 thread safe (https://jira.springsource.org/browse/SPR-5863)에서 벗어나는 것으로부터 온다고 생각하지 않습니까?

    이것은 오히려 org.springframework.test.context.TestContextManager가 thread safe (https://jira.springsource.org/browse/SPR-5863)에서 벗어나는 것으로부터 온다고 생각하지 않습니까?

    Transactional TestNG 테스트를 병렬로 시작하고자 할 때도 똑같은 문제에 봉착했으며 실제로 Spring이 트랜잭션을 올바른 Thread에 바인드하려고 시도한다는 것을 알 수 있습니다.

    그러나 이것은 이런 종류의 오류로 무작위로 실패합니다. 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);
    }
    

    (동기화되는 키 ...)

    지금은 매력처럼 작동하고 있습니다. 나는 완전히 마비 될 수 있기 때문에 봄 3.2를 기다릴 수 없다!

  3. from https://stackoverflow.com/questions/2202045/testng-multithreaded-test-with-spring-transactional by cc-by-sa and MIT license