2010-11-12 5 views
34

Nie mam problemu z testowaniem moich DAO i usług, ale kiedy testuję INSERT s lub UPDATE s, chcę wycofać transakcję i nie wpłynąć na moją bazę danych.Jak wycofać transakcję bazy danych podczas testowania usług ze Spring w JUnit?

Używam usług @Transactional w ramach moich usług do zarządzania transakcjami. Chcę wiedzieć, czy możliwe jest sprawdzenie, czy transakcja będzie w porządku, ale czy można ją wycofać, aby zapobiec zmianie bazy danych?

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

Problem polega na tym, że ten test nie powiedzie się, ponieważ transakcja została rollbacked, ale wkładka jest OK! Jeśli usuniemy @TransactionConfiguration(defaultRollback=true), wówczas testowanie zostanie zakończone, ale nowy rekord zostanie wstawiony do bazy danych.

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

Teraz można przetestować poprawnie, ale wycofanie jest ignorowane, a rekord jest wstawiany do bazy danych. Mam oczywiście metodę opisaną addPerson() wewnątrz myService z @Transactional. Dlaczego przywracanie jest ignorowane?

+0

dobre pytanie +1 :-) –

Odpowiedz

28

należy rozszerzyć granice transakcyjnych do granic swojej metody badania. Można to zrobić poprzez opisywanie metodę testową (lub całą klasę test) jako @Transactional:

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

Można również użyć tej metody, aby upewnić się, że dane zostały poprawnie napisane przed wycofywania:

@Autowired SessionFactory sf; 

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

cześć, teraz test pass, ale wycofanie zostało zignorowane. Mam @Transactional nad "testAddPerson" i nad "addPerson". – blow

+0

Jeśli usuwam @Transactional z myService, nie ma aktywnej transakcji dla testu, więc myślę, że @Transactional nad "testAddPerson" nie działa ... – blow

+5

@blow: Właśnie zauważyłem, że masz 'extends AbstractJUnit38SpringContextTests'. Nie jest to potrzebne, ponieważ masz test JUnit 4 z '@ RunWith'. – axtavt

2

Wyjazd

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

Sekcja 8.3.4 w szczególności

Wiosna ma jakieś zajęcia dla testów, które będą zawijać każdy test w transakcji, więc DB nie ulega zmianie. Możesz także zmienić tę funkcję, jeśli chcesz.

Edit - w oparciu o informacje o więcej, warto spojrzeć na

AbstractTransactionalJUnit38SpringContextTests na

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

+0

cześć miałem więcej informacji. – blow

+0

@blow - zaktualizowałem moją odpowiedź. – hvgotcodes

+0

dziękuję, to jest przydatne, znalazłem mały problem w mojej realizacji. Teraz mam inny problem, wycofanie jest ignorowane – blow

0

Jeśli Twój opis jest adnotowany jak @ Transactional, a otrzymasz inny rodzaj lub błędy, próbując naprawić ten błąd. Powrót na górę Więc lepiej po prostu przetestuj metody DAO.

1

używać następujących adnotacji przed klasą:

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

tutaj txManager jest kontekst aplikacji Menedżer transakcji.

Tutaj txManager jest instancją lub identyfikatorem komponentu menedżera transakcji od application context.

<!-- Transaction Manager --> 
    <bean id="txManager" 
      class="org.springframework.orm.hibernate3.HibernateTransactionManager"> 
     <property name="sessionFactory" ref="sessionFactory" /> 
    </bean> 

    <tx:annotation-driven transaction-manager="txManager" /> 

Dodaj swój kod wewnątrz setUp() metoda ta będzie wykonywał w początku badania oraz ostatniego zawinąć kod należy umieścić w teatDown() metodę, która będzie wykonywany w końcu. lub możesz zamiast tego użyć adnotacji @Before i.