Domanda

Sto usando TestNG per testare moduli persistenza di primavera (JPA + Hibernate) utilizzando AbstractTransactionalTestNGSpringContextTests come classe base. Tutte le parti importanti @Autowired, @TransactionConfiguration, lavoro @Transactional bene.

Il problema nasce quando sto cercando di eseguire il test in filetti paralleli con threadPoolSize = x, y = invocationCount annotazione 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)

... Qualcuno ha affrontato questo problema?

Ecco il codice:

@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);
    ...
}
...

Aggiornamento: Sembra che AbstractTransactionalTestNGSpringContextTests mantiene transazione solo per i thread principale quando tutti gli altri thread di test non ottengono la loro propria istanza di transazione. L'unico modo per risolvere questo è di estendere AbstractTestNGSpringContextTests e mantenere operazione di programmazione (invece di annotazione @Transactional) per ciascun metodo (cioè con 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
        }
    }
}
È stato utile?

Soluzione

La transazione deve essere avviato nello stesso thread, qui ci sono ulteriori dettagli:

Spring3 / Hibernate3 / TestNG: alcuni test danno LazyInitializationException, alcuni non

Altri suggerimenti

Non pensi che questo piuttosto viene da org.springframework.test.context.TestContextManager non essere thread-safe (vedi https://jira.springsource.org/browse/SPR-5863 )?

Ho affrontato lo stesso problema quando ho voluto lanciare i miei test TestNG transazionali in parallelo e si può vedere che la primavera in realtà tenta di associare la transazione al thread destra.

Tuttavia questo non funziona in modo casuale con questo tipo di errori. Ho esteso AbstractTransactionalTestNGSpringContextTests con:

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

(la chiave nella sincronizzazione ...)

ed ora sta lavorando come un fascino. Non vedo l'ora per la primavera 3.2 anche se in modo che possa essere completamente parallized!

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top