2010-07-20 6 views
1

Quand j'utilise org.junit.rules.Timeout JUnit avec les AbstractTransactionalJUnit4SpringContextTests de classe de base de printemps, je reçois cette exception:Utiliser délai d'attente @Rule de Junit 4 avec les AbstractTransactionalJUnit4SpringContextTests de printemps

org.springframework.dao.InvalidDataAccessApiUsageException: no transaction is in progress; nested exception is javax.persistence.TransactionRequiredException: no transaction is in progress 

La sortie affiche du journal:

2010-07-20 09:20:16 INFO [TransactionalTestExecutionListener.startNewTransaction] Began transaction (1): transaction manager [[email protected]]; rollback [true] 
2010-07-20 09:20:16 INFO [TransactionalTestExecutionListener.endTransaction] Rolled back transaction after test execution for test context [[[email protected] testClass = MyIntegrationTest, locations = array<String>['classpath:/context.xml', 'classpath:/junit-context.xml'], testInstance = [email protected], testMethod = [email protected], testException = org.springframework.dao.InvalidDataAccessApiUsageException: no transaction is in progress; nested exception is javax.persistence.TransactionRequiredException: no transaction is in progress]] 

Voici mon test:

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration(locations = {"classpath:/context.xml", "classpath:/junit-context.xml"}) 
@TransactionConfiguration(transactionManager = "transactionManager", defaultRollback = true) 
@Transactional 
public class MyIntegrationTest extends AbstractTransactionalJUnit4SpringContextTests{ 

    @Rule public Timeout globalTimeout = new Timeout(30000); 

    @Test 
    public void myTest() { 
     // transactional code here saving to the database... 
    } 
} 

Toutefois, lorsque jamais je commente la règle, tout fonctionne bien.

Comment puis-je marier ces deux ensemble pour fonctionner correctement?

+0

J'ai compris que la classe Timeout démarre un nouveau thread et exécute mon test dedans. C'est pourquoi ma transaction est créée mais mon code n'est pas inclus. Maintenant, pour comprendre comment le faire fonctionner comment je veux ... – JavaRocky

+0

La raison pour laquelle le journal montre une transaction en cours d'installation et d'arrêt, c'est qu'il vit sur le fil d'origine sur lequel la minuterie vit actuellement. Et probablement parce que la transaction utilise une sorte d'instance ThreadLocal, mon code n'est pas enveloppé dans une transaction. – JavaRocky

Répondre

0

LOL.

Vous pouvez simplement aussi annoter votre méthode de test avec @Transactional (timeout = 30) pendant 30 secondes. Ce qui est beaucoup plus simple.

+0

Notez que le délai d'attente est en millisecondes et non en secondes. – Adam

+0

Il se peut que l'annotation d'un seul test ne soit pas vraiment utile si le délai d'attente doit être appliqué à de nombreux tests. Pensez à plus de tests dans les sous-classes de MyIntegrationTest. Le nom de la variable globalTimeout suggère que le délai d'expiration doit être appliqué à plusieurs tests. – rwitzel

0

Ahh, je me suis débrouillé. La façon dont je l'ai résolu était de configurer la transaction par programme.

@Autowired TransactionManager transactionManager; 

@Test 
public void test() {  
    TransactionTemplate transactionTemplate = new TransactionTemplate(transactionManager); 
    transactionTemplate.execute(new TransactionCallbackWithoutResult() { 
     @Override 
     protected void doInTransactionWithoutResult(TransactionStatus status) { 
      status.setRollbackOnly(); 

      // DO YOUR TEST LOGIC HERE 
     } 
    }); 
} 

Espérons que cela aide.