Mam metodę DAO, która wykorzystuje Spring do dostępu JDBC. Oblicza wskaźnik sukcesu sprzedawcy w sprzedaży przedmiotu.
Oto kod:
public BigDecimal getSellingSuccessRate(long seller_id) {
String sql = "SELECT SUM(IF(sold_price IS NOT NULL, 1, 0))/SUM(1)
FROM transaction WHERE seller_id = ?";
Object[] args = {seller_id};
return getJdbcTemplate().queryForObject(sql, args, BigDecimal.class);
}
Jak powinienem przejść do testowania tej metody lub dowolnej metody DAO z JUnit? Jakie są najlepsze praktyki testowania logiki dostępu do danych? Zastanawiam się nad przetestowaniem go na bazie danych, którą można osadzić, załadowanej pewnymi danymi, ale czy nie powinniśmy wykonywać testów integracyjnych podobnych do środowiska produkcyjnego pod względem RDBMS i schematu?
java
programming-practices
testing
tdd
Michael
źródło
źródło
Odpowiedzi:
Problem z użyciem „prawdziwej” bazy danych do testowania jednostkowego polega na konfiguracji, demontażu i izolacji testów. Nie chcesz rozpędzać całkowicie nowej bazy danych MySQL i tworzyć tabele i dane tylko dla jednego testu jednostkowego. Problemy z tym związane są z zewnętrznym charakterem bazy danych, a testowa baza danych jest wyłączona, testy jednostkowe nie powiodły się. Występują również problemy z upewnieniem się, że masz unikalną bazę danych do testowania. Można je pokonać, ale istnieje prostsza odpowiedź.
Wyśmiewanie bazy danych jest jedną z opcji, jednak nie testuje faktycznie uruchomionych zapytań. Może być stosowany jako znacznie prostsze rozwiązanie, gdy chcesz mieć pewność, że dane z DAO przechodzą prawidłowo przez system. Ale do testowania samego DAO potrzebujesz czegoś, za czym DAO ma dane i zapytania działają poprawnie.
Pierwszą rzeczą do zrobienia jest użycie bazy danych w pamięci. HyperSQL jest doskonałym wyborem do tego celu, ponieważ ma możliwość emulacji dialektu innej bazy danych - dzięki czemu drobne różnice między bazami danych pozostają takie same (typy danych, funkcje i tym podobne). hsqldb ma również kilka fajnych funkcji do testowania jednostek.
Spowoduje to załadowanie stanu bazy danych (tabel, danych początkowych) z
testData
pliku.shutdown=true
automatycznie zamknie bazę danych po zamknięciu ostatniego połączenia.Korzystając z wstrzykiwania zależności , niech testy jednostkowe wybierają inną bazę danych niż ta, którą wykorzystują wersje produkcyjna (testowa lub lokalna).
Następnie DAO korzysta z wstrzykniętej bazy danych, dla której można uruchomić testy względem bazy danych.
Testy jednostkowe będą wtedy wyglądały następująco (kilka nudnych rzeczy nie jest zawartych dla zwięzłości):
I tak masz test jednostkowy, który wywołuje DAO i korzysta z danych skonfigurowanych w bazie danych w locie, która istnieje przez czas trwania testu. Nie musisz martwić się o zasoby zewnętrzne lub stan bazy danych przed uruchomieniem lub przywrócenie do znanego stanu (cóż, „znany stan” to „nie istnieje”, do którego przywrócenie jest banalne).
DBUnit może znacznie uprościć to, co opisałem, w prostszym procesie konfigurowania bazy danych, tworzenia tabel i ładowania danych. Jeśli z jakiegoś powodu będziesz musiał korzystać z rzeczywistej bazy danych, jest to zdecydowanie lepsze narzędzie do użycia.
Powyższy kod jest częścią projektu maven, który napisałem dla potwierdzenia koncepcji TestingWithHsqldb na github
źródło
sql.syntax_mys=true
zmiana sposobu działania hsqldb: „Ta właściwość, jeśli jest ustawiona na true, umożliwia obsługę typów TEKST i AUTO_INCREMENT, a także umożliwia zgodność z niektórymi innymi aspektami tego dialektu”. whilesql.syntax_ora=true
robi „Ta właściwość, jeśli jest ustawiona na true, umożliwia obsługę niestandardowych typów. Umożliwia także składnię DUAL, ROWNUM, NEXTVAL i CURRVAL, a także umożliwia zgodność z niektórymi innymi aspektami tego dialektu”.Po pierwsze, nigdy nie należy przeprowadzać testów w środowisku produkcyjnym. Powinieneś mieć środowisko testowe, które odzwierciedla środowisko produkcyjne i przeprowadzać tam testy integracyjne.
Jeśli to zrobisz, możesz zrobić wiele rzeczy.
źródło
W naszym projekcie każdy programista prowadzi pustą bazę danych, jej struktura jest taka sama jak produkcyjna baza danych.
W każdym teście jednostkowym TestInitialize tworzymy połączenie i transakcję z bazą danych oraz niektóre domyślne obiekty potrzebne do każdego testu. I wszystko jest wycofywane po zakończeniu każdej metody lub klasy.
W ten sposób można przetestować warstwę SQL. W rzeczywistości każde zapytanie lub wywołanie bazy danych musi zostać przetestowane w ten sposób.
Minusem jest to, że jest powolny, dlatego umieszczamy go w innym projekcie niż nasze regularne testy jednostkowe. Można to przyspieszyć za pomocą bazy danych w pamięci, ale pomysł pozostaje ten sam.
źródło