web-dev-qa-db-fra.com

Annulation de transaction après @Test

Tout d’abord, j’ai trouvé beaucoup de discussions sur StackOverflow à ce sujet, mais aucune d’entre elles ne m’a vraiment aidée. Je suis donc désolé de poser une question qui pourrait être dupliquée.

J'exécute des tests JUnit en utilisant spring-test, mon code ressemble à ceci

@RunWith(SpringJUnit4ClassRunner.class)  
@ContextConfiguration(locations = {})
public class StudentSystemTest {

    @Autowired
    private StudentSystem studentSystem;

    @Before
    public void initTest() {
    // set up the database, create basic structure for testing
    }

    @Test
    public void test1() {
    }    
    ...  
}

Mon problème est que je veux que mes tests n'influencent pas les autres tests. Je voudrais donc créer quelque chose comme une restauration pour chaque test. J'ai beaucoup cherché, mais je n'ai rien trouvé jusqu'à présent. J'utilise Hibernate et MySql pour cela

65
Jan Vorcak

Ajoutez simplement @Transactional annotation en plus de votre test:

@RunWith(SpringJUnit4ClassRunner.class)  
@ContextConfiguration(locations = {"testContext.xml"})
@Transactional
public class StudentSystemTest {

Par défaut, Spring lancera une nouvelle transaction entourant votre méthode de test et @Before/@After callbacks, annulant à la fin. Cela fonctionne par défaut, il suffit d'avoir un gestionnaire de transaction dans le contexte.

De: 10.3.5.4 Gestion des transactions (gras, mine):

Dans la structure TestContext, les transactions sont gérées par TransactionalTestExecutionListener. Notez que TransactionalTestExecutionListener est configuré par défaut , même si vous ne déclarez pas explicitement @TestExecutionListeners sur votre classe de test. Pour activer la prise en charge des transactions, vous devez toutefois fournir un bean PlatformTransactionManager dans le contexte d'application chargé par @ContextConfiguration sémantique. De plus, vous devez déclarer @Transactional soit au niveau de la classe ou de la méthode pour vos tests .

110
Tomasz Nurkiewicz

A part: tentative de modification de la réponse de Tomasz Nurkiewicz a été rejetée:

Cette modification ne rend pas le message, même un peu plus facile à lire, plus facile à trouver, plus précis ou plus accessible. Les modifications sont soit totalement superflues, soit nuisent activement à la lisibilité.


Correct et permanent lien vers la section correspondante de la documentation sur les tests d'intégration.

Pour activer la prise en charge des transactions, vous devez configurer un bean PlatformTransactionManager dans le fichier ApplicationContext chargé via @ContextConfiguration sémantique.

 @ Configuration 
 @ PropertySource ("application.properties") 
 Public class Persistence {
 @Autowired 
 Environment env; 
 
 @Bean 
 DataSource dataSource () {
 Renvoie un nouveau DriverManagerDataSource (
 Env.getProperty ("datasource.url"), 
 Env.getProperty ("datasource.user"), 
 env.getProperty ("datasource.password") 
); 
} 
 
 @Bean 
 PlatformTransactionManager transactionManager () {
 Renvoie new DataSourceTransactionManager (dataSource ()); 
} 
} 

De plus, vous devez déclarer le printemps @Transactional annotation au niveau de la classe ou de la méthode pour vos tests.

 @ RunWith (SpringJUnit4ClassRunner.class) 
 @ ContextConfiguration (classes = {Persistence.class, SomeRepository.class}) 
 @ Transactionnelle 
 Classe publique SomeRepositoryTest {.. .} 

Annoter une méthode de test avec @Transactional provoque l'exécution du test dans une transaction qui, par défaut, sera automatiquement annulée une fois le test terminé. Si une classe de test est annotée avec @Transactional, chaque méthode de test dans cette hiérarchie de classe sera exécutée dans une transaction.

15
user2418306

Les réponses mentionnant l'ajout de @Transactional sont corrects, mais pour des raisons de simplicité, vous pourriez avoir votre classe de test extends AbstractTransactionalJUnit4SpringContextTests.

11
matt b

Je sais que je suis trop tard pour poster une réponse, mais en espérant que cela puisse aider quelqu'un. De plus, je viens de résoudre ce problème que j'avais avec mes tests. Voici ce que j'avais dans mon test:

Ma classe de test

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "path-to-context" })
@Transactional
public class MyIntegrationTest 

Contexte xml

<bean id="dataSource" class="org.Apache.commons.dbcp.BasicDataSource">
   <property name="driverClassName" value="${jdbc.driverClassName}" />
   <property name="url" value="${jdbc.url}" />
   <property name="username" value="${jdbc.username}" />
   <property name="password" value="${jdbc.password}" />
</bean>

J'ai toujours eu le problème suivant: la base de données n'était pas nettoyée automatiquement.

Le problème a été résolu lorsque j'ai ajouté la propriété suivante à BasicDataSource

<property name="defaultAutoCommit" value="false" />

J'espère que ça aide.

4
Atul Kumbhar

Vous devez exécuter votre test avec un contexte de sprint et un gestionnaire de transactions, par exemple,

@RunWith(SpringJUnit4ClassRunner.class)  
@ContextConfiguration(locations = {"/your-applicationContext.xml"})
@TransactionConfiguration(transactionManager="txMgr")
public class StudentSystemTest {

     @Test
     public void testTransactionalService() {
         // test transactional service
     }

     @Test
     @Transactional
     public void testNonTransactionalService() {
         // test non-transactional service
     }
}

Voir le chapitre 10. Testing de la référence Spring pour plus de détails.

0
Johan Sjöberg