Pergunta

Eu estou usando TestNG para teste de persistência módulos Primavera (JPA + Hibernate) usando AbstractTransactionalTestNGSpringContextTests como uma classe base. Todas as peças importantes @Autowired, @TransactionConfiguration, trabalho @Transactional muito bem.

O problema surge quando eu estou tentando executar o teste em threads paralelas com threadPoolSize = x, invocationCount = y TestNG anotação.

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)

... Tem alguém enfrentou esse problema?

Aqui está o código:

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

Update: Parece que AbstractTransactionalTestNGSpringContextTests mantém transação apenas para thread principal quando todos os outros tópicos de teste não obter a sua própria instância transação. A única maneira de resolver que consiste em estender AbstractTestNGSpringContextTests e manter transacção por meio de programação (em vez de anotação @Transactional) por cada um dos métodos (isto é, com 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
        }
    }
}
Foi útil?

Solução

A transação precisa ser iniciado no mesmo segmento, aqui estão mais detalhes:

Spring3 / Hibernate3 / TestNG: alguns testes dão LazyInitializationException, alguns não

Outras dicas

Você não acha que esta vez vem de org.springframework.test.context.TestContextManager não ser thread-safe (veja https://jira.springsource.org/browse/SPR-5863 )?

Eu enfrentei o mesmo problema quando eu quis lançar meus testes transacional TestNG em paralelo e você pode ver que a Primavera realmente tenta ligar a transação para o segmento direito.

No entanto, esta falha aleatoriamente com este tipo de erros. Eu estendi AbstractTransactionalTestNGSpringContextTests com:

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

(a tecla a ser o sincronizado ...)

e está agora trabalhando como um encanto. Eu não posso esperar para a Primavera de 3,2 embora assim que ele pode ser completamente parallized!

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top