2012-09-27 14 views
48

Prima di tutto, ho trovato molti thread su StackOverflow a questo proposito, ma nessuno di questi mi ha veramente aiutato, mi spiace quindi di porre una possibile domanda doppia.Transazione di rollback dopo @Test

Io corro test JUnit usando primavera-test, il mio codice simile a questo

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

mio problema è che voglio che i miei test di non influenzare gli altri test. Quindi mi piacerebbe creare qualcosa come il rollback per ogni test. Ho cercato molto per questo, ma non ho trovato nulla finora. Sto usando Hibernate e MySql per questo

+0

Cosa intendi con rollback ?. Pulizia del database? – Gaurav

+3

impostandolo allo stesso identico stato in cui si trovava dopo l'esecuzione di 'initTest' –

risposta

84

Basta aggiungere @Transactional annotazione sulla parte superiore del test:

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

Per impostazione predefinita primavera inizierà una nuova transazione che circonda il vostro metodo di prova e @Before/@After callback, rollback alla fine. Funziona di default, è sufficiente avere qualche gestore delle transazioni nel contesto.

Da: 10.3.5.4 Transaction management (miniera grassetto):

Nel quadro TestContext, le transazioni sono gestite dal TransactionalTestExecutionListener. Si noti che TransactionalTestExecutionListener è configurato per impostazione predefinita, anche se non si dichiara esplicitamente @TestExecutionListeners nella classe di test. Per abilitare il supporto per le transazioni, tuttavia, è necessario fornire un bean PlatformTransactionManager nel contesto dell'applicazione caricato dalla semantica @ContextConfiguration. Inoltre, è necessario dichiarare @Transactional a livello di classe o di metodo per i test.

+0

beh, l'ho provato prima, e non funziona ancora, forse ... il problema può essere che non ho definito PlatformTransactionManager, come posso farlo? –

+0

@javo: come stai modificando il database? Se stai usando Jpa/Hibernate/JdbcTemplate/... ci deve essere un "PlatformTransactionManager". Altrimenti come saprà la primavera delle tue transazioni e del tuo database? –

+0

Il collegamento in questa risposta non è più corretto; vedere la risposta [user2418306 sotto] (http://stackoverflow.com/a/35943700/325900) per il collegamento corretto e più contesto dalla documentazione Spring. – DaveyDaveDave

0

È necessario eseguire il test con un contesto sprint e un gestore delle transazioni, ad esempio,

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

Vedere il capitolo 10. Testing di riferimento Primavera per ulteriori dettagli.

8

Le risposte che citano l'aggiunta @Transactional sono corretti, ma per semplicità si può solo avere la vostra classe di test extends AbstractTransactionalJUnit4SpringContextTests.

+0

aggiungendo annotazioni '@Transactional' sul livello di classe non funziona, aggiungendo annotazioni '@Transactional' separatamente per ogni funzione funziona, e si estende AbstractTransactionalJUnit4SpringContextTests lavora troppo – user3871754

-5

È possibile disattivare il rollback:

@TransactionConfiguration(defaultRollback = false) 

Esempio:

@RunWith(SpringJUnit4ClassRunner.class) 
@SpringApplicationConfiguration(classes = Application.class) 
@Transactional 
@TransactionConfiguration(defaultRollback = false) 
public class Test { 
    @PersistenceContext 
    private EntityManager em; 

    @org.junit.Test 
    public void menge() { 
     PersistentObject object = new PersistentObject(); 
     em.persist(object); 
     em.flush(); 
    } 
} 
+3

Questo è esattamente l'opposto di quello che l'OP sta chiedendo per –

2

lo so, io sono tooooo tardi per inviare una risposta, ma nella speranza che possa aiutare qualcuno. Inoltre, ho appena risolto questo problema che ho avuto con i miei test. Questo è quello che avevo nel mio test:

La mia classe di test

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

Contesto 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> 

ho ancora avuto il problema che, il database non veniva ripulito automaticamente.

problema è stato risolto quando ho aggiunto seguente proprietà di BasicDataSource

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

Speranza che aiuta.

+0

Bene, quindi si impegnano le dichiarazioni manualmente? Sei sicuro che i tuoi dati siano stati scritti anche nel tuo database? –

11

parte: tentativo di modificare la risposta di Tomasz Nurkiewicz è stata respinta:

Questa modifica non rende il posto anche un po 'più facile da leggere, più facile da trovare, più accurato e più accessibile. I cambiamenti sono completamente superflui o danneggiano attivamente la leggibilità.


corretta e permanente link alla relativa sezione di documentazione su test di integrazione.

per abilitare il supporto per le transazioni, è necessario configurare un PlatformTransactionManager fagiolo nel ApplicationContext che viene caricato tramite @ContextConfiguration semantica.

 
@Configuration 
@PropertySource("application.properties") 
public class Persistence { 
    @Autowired 
    Environment env; 

    @Bean 
    DataSource dataSource() { 
     return new DriverManagerDataSource(
       env.getProperty("datasource.url"), 
       env.getProperty("datasource.user"), 
       env.getProperty("datasource.password") 
     ); 
    } 

    @Bean 
    PlatformTransactionManager transactionManager() { 
     return new DataSourceTransactionManager(dataSource()); 
    } 
} 

Inoltre, è necessario dichiarare @Transactional annotazione di primavera sia a livello di classe o un metodo per i test.

 
@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration(classes = {Persistence.class, SomeRepository.class}) 
@Transactional 
public class SomeRepositoryTest { ... } 

Annotazione un metodo di test con @Transactional provoca il test da eseguire all'interno di una transazione che, per impostazione predefinita, automaticamente il rollback dopo il completamento del test. Se una classe di test è annotata con @Transactional, ciascun metodo di prova all'interno di tale gerarchia di classi verrà eseguito all'interno di una transazione.

Problemi correlati