Come eseguire il rollback di una transazione di database durante il test dei servizi con Spring in JUnit?

Non ho problemi a testare il mio DAO e servizi, ma quando provo INSERT s o UPDATE s voglio eseguire il rollback della transazione e non influire sul mio database.

Sto usando @Transactional all’interno dei miei servizi per gestire le transazioni. Voglio sapere, è ansible sapere se una transazione andrà bene, ma ripristinarla per evitare di alterare il database?

Questo è il mio test:

 @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = "classpath:/META-INF/spring.cfg.xml") @TransactionConfiguration(defaultRollback=true) public class MyServiceTest extends AbstractJUnit38SpringContextTests { @Autowired private MyService myService; @BeforeClass public static void setUpClass() throws Exception { } @AfterClass public static void tearDownClass() throws Exception { } @Test public void testInsert(){ long id = myService.addPerson( "JUNIT" ); assertNotNull( id ); if( id < 1 ){ fail(); } } } 

Il problema è che questo test fallirà perché la transazione è stata sottoposta a rollback, ma l’inserimento è OK! Se rimuovo @TransactionConfiguration(defaultRollback=true) il test pass ma un nuovo record verrà inserito nel database.

 @Test @Transactional @Rollback(true) public void testInsert(){ long id = myService.addPerson( "JUNIT" ); assertNotNull(id); if( id < 1 ){ fail(); } } 

Ora il test può passare correttamente, ma il rollback viene ignorato e il record viene inserito nel database. Ho annotato il metodo addPerson() all’interno di myService con @Transactional , ovviamente. Perché il rollback viene ignorato?

    È necessario estendere i limiti della transazione ai limiti del metodo di prova. Puoi farlo annotando il tuo metodo di test (o l’intera class di test) come @Transactional :

     @Test @Transactional public void testInsert(){ long id=myService.addPerson("JUNIT"); assertNotNull(id); if(id<1){ fail(); } } 

    Puoi anche utilizzare questo approccio per garantire che i dati siano stati scritti correttamente prima del rollback:

     @Autowired SessionFactory sf; @Test @Transactional public void testInsert(){ myService.addPerson("JUNIT"); sf.getCurrentSession().flush(); sf.getCurrentSession().doWork( ... check database state ... ); } 

    check-out

    http://static.springsource.org/spring/docs/2.5.x/reference/testing.html

    In particolare la sezione 8.3.4

    Spring ha alcune classi per i test che completano ogni test in una transazione, quindi il DB non viene modificato. Puoi cambiare questa funzionalità se vuoi anche tu.

    Modifica – in base alle tue più informazioni, potresti voler guardare

    AbstractTransactionalJUnit38SpringContextTests su

    http://static.springsource.org/spring/docs/2.5.x/api/org/springframework/test/context/junit38/AbstractTransactionalJUnit38SpringContextTests.html

    Usa l’annotazione seguente prima della lezione:

     @TransactionConfiguration(transactionManager = "txManager",defaultRollback = true) @Transactional 

    qui txManager è Transaction Manager del contesto dell’applicazione.

    Qui txManager è un’istanza o bean id di Transaction Manager dal application context .

          

    Aggiungi il tuo codice all’interno del metodo setUp() , questo verrà eseguito all’inizio del test e l’ultimo codice di avvolgimento dovrebbe essere inserito nel metodo teatDown() che verrà eseguito alla fine. oppure puoi usare @Before e @After posto dell’annotazione.

    Se tuo

     myService.addPerson("JUNIT"); 

    il metodo è annotato come @Transactional, si otterrà un tipo diverso o errori che cercano di risolvere questo problema. Quindi è meglio testare i metodi DAO.