2012-09-27 24 views
48

Po pierwsze, znalazłem wiele wątków na temat StackOverflow na ten temat, ale żaden z nich naprawdę mi nie pomógł, więc przepraszam, że mogę zadać duplikat pytania.Transakcja wycofania po @ Test

biegnę testy JUnit za pomocą sprężyny test, mój kod wygląda następująco

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

Mój problem jest, że chcę moje testy nie wpływają na inne testy. Więc chciałbym stworzyć coś w rodzaju rollback dla każdego testu. Wiele już szukałem, ale niczego nie znalazłem. używam hibernacji i MySQL do tego

+0

Co masz na myśli przez wycofanie? Czyszczenie bazy danych? – Gaurav

+3

ustawiając dokładnie taki sam stan, jaki był po wykonaniu 'initTest' –

Odpowiedz

84

Wystarczy dodać @Transactional adnotacji na szczycie Twojego testu:

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

Domyślnie wiosnę rozpocznie nową transakcję otaczający metodę testową i @Before/@After zwrotnych, wycofywanie na końcu. Działa domyślnie, wystarczy mieć jakiegoś menedżera transakcji w kontekście.

Od: 10.3.5.4 Transaction management (wytłuszczenie moje):

W ramach TestContext transakcje są zarządzane przez TransactionalTestExecutionListener. Zauważ, że TransactionalTestExecutionListener jest skonfigurowany domyślnie, nawet jeśli nie jawnie zadeklarujesz @TestExecutionListeners na swojej klasie testowej. Aby włączyć obsługę transakcji, należy jednak podać komponent bean PlatformTransactionManager w kontekście aplikacji załadowanym semantyką @ContextConfiguration. Ponadto, musisz zadeklarować @Transactional na poziomie klasy lub metody dla swoich testów.

+0

, próbowałem tego wcześniej i nadal nie działa, może ... może być problem z tym, że nie zdefiniowałem PlatformTransactionManager, jak czy mogę to zrobić? –

+0

@javo: w jaki sposób modyfikujesz bazę danych? Jeśli używasz Jpa/Hibernate/JdbcTemplate/... musi to być 'PlatformTransactionManager'. Inaczej jak Spring dowie się o twoich transakcjach i bazie danych? –

+0

Link w tej odpowiedzi nie jest już poprawny; zobacz odpowiedź [user2418306 poniżej] (http://stackoverflow.com/a/35943700/325900) dla poprawnego linku i więcej kontekstu z dokumentacji Spring. – DaveyDaveDave

0

trzeba uruchomić test z kontekstu sprintu i menedżer transakcji, np

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

Patrz rozdział 10. Testing z odniesieniem Wiosny w dalsze szczegóły.

8

Odpowiedzi przywołujące dodanie @Transactional są poprawne, ale dla uproszczenia można po prostu mieć swoją klasę testową extends AbstractTransactionalJUnit4SpringContextTests.

+0

dodanie adnotacji "@Transactional" na poziomie klasy nie działa, dodawanie adnotacji "@Transactional" osobno dla każdej funkcji działa i rozszerza AbstractTransactionalJUnit4SpringContextTests działa również – user3871754

-5

Można wyłączyć przywracania:

@TransactionConfiguration(defaultRollback = false) 

Przykład:

@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

To jest dokładnie odwrotnie, co OP żąda od –

2

wiem, jestem tooooo późno aby umieścić odpowiedź, ale z nadzieją, że może komuś pomóc. Plus, właśnie rozwiązałem ten problem, który miałem z moimi testami. To jest to, co miałem w moim teście:

moja klasa Test

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

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

wciąż miałem problem, że baza danych nie był czyszczony automatycznie.

problem został rozwiązany, gdy dodałem następującą właściwość do BasicDataSource

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

Nadzieję, że to pomaga.

+0

Cóż, więc zatwierdzasz swoje instrukcje ręcznie? Jesteś pewien, że twoje dane były nawet zapisane w twojej bazie danych? –

11

marginesie: próba zmiany odpowiedź Tomasz Nurkiewicz została odrzucona:

Ta edycja nie czyni post nawet trochę bardziej czytelne i łatwiejsze do znalezienia, bardziej dokładne i bardziej dostępne. Zmiany są albo całkowicie zbędne, albo aktywnie szkodzą czytelności.


Prawidłowe i trwałe link do odpowiedniej sekcji dokumentacji na temat testów integracyjnych.

Aby włączyć wsparcie dla transakcji, należy skonfigurować PlatformTransactionManager fasoli w ApplicationContext który jest ładowany poprzez @ContextConfiguration semantyki.

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

Ponadto należy zadeklarować Wiosny @Transactional adnotacji albo na poziomie klasy lub metody dla swoich badań.

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

adnotacji metodę testową z @Transactional powoduje testy mają być uruchamiane w ramach transakcji, która będzie domyślnie automatycznie cofnięty po zakończeniu testu. Jeśli klasa testowa ma przypisaną wartość @Transactional, każda metoda testowa w tej hierarchii klas będzie uruchamiana w ramach transakcji.