2010-06-09 9 views
12

Test sprężynowy pomocny wycofuje wszelkie zmiany wprowadzone do bazy danych w ramach metody testowej. Oznacza to, że nie jest konieczne poświęcenie czasu na usunięcie/ponowne załadowanie danych testowych przed każdą metodą testową.Jak załadować dane testowe DBUnit raz na skrzynkę za pomocą testu sprężynowego

Ale jeśli używasz adnotacji @BeforeClass Junit, to zmusza ładowarkę danych do statycznego. Pytanie, które jest tutaj badane: Why must jUnit's fixtureSetup be static?

Jeśli metoda inicjowania danych jest statyczna, to również metody połączenia danych i źródło danych .. i tak dalej ... zmuszając wszystko do statycznego ... które wygrało ' t działa. W którym momencie pytam - co jest dobre, Spring Test ma możliwość wycofywania zmian, gdy trzeba usunąć/wczytać dane testowe mimo to dla każdego testu?!?!

Odpowiedz

14

Jedną z metod, która działa, jest utworzenie klasy "inicjalizator danych", dodanie jej do kontekstu aplikacji testowej Wiosna, która również ma źródło danych i podłączenie kontekstu aplikacji do testów. To opiera się na fakcie, że Spring buforuje kontekst aplikacji między wywołaniami testu.

Na przykład nadklasą Test:

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration(locations={"classpath:test-application-context.xml"}) 
@Transactional 
public abstract class DataLoadingTest { 
    @Autowired 
    protected DatabaseInitialiser databaseInitialiser; 
} 

Z test-application-context.xml:

<beans xmlns="http://www.springframework.org/schema/beans" 
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
     xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> 
    <bean id="dataSource" .../> 

    <bean class="DatabaseInitialiser"> 
     <property name="dataSource" ref="dataSource"/> 
    </bean> 
</beans> 

I

public class DatabaseInitialiser extends JdbcDaoSupport { 
    @PostConstruct 
    public void load() { 
     // Initialise your database here: create schema, use DBUnit to load data, etc. 
    } 
} 

W tym przykładzie:

  • wszystkie testy bazujące na bazie danych rozszerzają się na DataLoadingTest;
  • Sprężyna inicjalizuje kontekst aplikacji po pierwszym wywołaniu testu;
  • to wywołanie DatabaseInitialiser.load(), za pomocą adnotacji @PostConstruct;
  • Wiosna zachowuje kontekst aplikacji w pamięci podręcznej;
  • Dalszy test wywołania drutu w DatabaseInitialiser z kontekstu aplikacji, który jest już buforowany;
  • testy są transakcyjne i wycofują się na końcu do początkowego zestawu danych.

Podobnie DatabaseInitialiser może mieć metody opisywane @PostDestroy wykonywać żadnych wycofywania potrzeby na końcu całego testu.

+0

To jest dokładnie to, w jaki sposób rozwiązałem problem, po prostu zapomniałem umieścić mój kod/odpowiedź z powrotem w SO. Dziękuję za poświęcenie czasu, aby zrobić to dla następnego faceta. – HDave

+0

Brzmi dobrze, ale w praktyce "@PostConstruct" z drugiej klasy działa wcześniej niż DatabaseInitialiser, więc nie ma sensu. Dzięki za pomoc. –

+0

@ zjednoczona ekspresja: czy możesz to rozwinąć? Którą inną klasę masz na myśli? W podanym przykładzie Spring inicjuje inicjalizator bazy danych przed klasą testową, która działa w sekcji Cass podanej w pytaniu. – Kkkev

1

Spring Test i DbUnit to dwie doskonałe struktury. Ale nie ma sensu ich łączyć. Ponieważ test sprężynowy wykonuje wycofanie na połączeniu, oczyszcza się później, podczas gdy DbUnit czyści i wstawia dane testowe w metodzie @Before.

Użyj sprężyny, jeśli nie jesteś zależny od żadnych dynamicznych danych i dbUnit w przeciwnym razie.

+0

Uważam, że zdolność DBUnit do ładowania tabeli bazy danych z XML jest wygodna. Czy test sprężynowy ma taką możliwość? – HDave

+1

Tak, myślę, że Mats się tu myli. Ładowanie danych testowych z pliku XML jest przyjemną korzyścią dla testów db z wiosną. – IcedDante

1

Używamy DBUnit w połączeniu z testem sprężynowym. Ale nie używamy funkcji DBUnit do usuwania danych po zakończeniu testu.

Dodajemy kilka insertów DBUnit do naszych danych testowych w metodzie @ Begefore w celu zainicjowania testu. Następnie, po zakończeniu testu, funkcja przywracania sprężyn przywraca bazę danych do pierwotnego stanu.

Największym problemem jest to, że dane DBUnit muszą zostać wczytane przed każdym testem, co może być dużym hitem wydajności. Większość naszych testów korzystających z DBUnit jest tylko do odczytu, testując zachowanie aplikacji w oparciu o pewne predefiniowane zachowanie. Mamy więc zwyczaj tworzenia testów głównych, które następnie przeprowadzają wszystkie testy drobnoziarniste w partii w ramach tej samej transakcji.

+1

Cóż, to jest zła praktyka. Co sądzisz o sprawdzonym rozwiązaniu? – IcedDante

0

Metody annotated with @BeforeTransaction działają, jak sugeruje jej nazwa, przed rozpoczęciem transakcji każdego testu. Jeśli w takiej metodzie można wykryć, czy dane testowe są załadowane, można załadować dane w razie potrzeby.

Należy jednak pamiętać, że dane pozostały w bazie danych (w pamięci) dla kolejnych wszystkich kolejnych.

Używamy tego do ładowania "statycznych" danych, które w środowisku produkcyjnym byłyby również ładowane do naszej bazy danych podczas uruchamiania. W ten sposób używamy dokładnie tego samego kodu i danych do naszych testów, zamiast polegać na eksportach (DbUnit), które mogą stać się nieaktualne.

Powiązane problemy