2009-08-05 12 views
30

To trochę dziwne pytanie, ale od kilku miesięcy dręczy mnie to. Zbudowałem aplikację internetową opartą na JPA, używając Wicket + Hibernate (zbudowany z Maven) i chcę przetestować warstwę DAO bezpośrednio. Stworzyłem specjalny plik src/test/resources/META-INF/persistence.xml, którego użyłem do testowania, ale które były w konflikcie z WTP i tym podobne. Aby obejść te problemy, utworzyłem osobny projekt testowy, w którym jednostka testuje na żywo. Czy istnieje lepszy sposób na zarządzanie testami jednostkowymi dla projektu JPA bez pojedynków między plikami trwałości?Test JUnit oparty na JPA Test Best Practices

Dodatek: Czy inne ramy testowe (na przykład TestNG) ułatwią to zadanie?

+0

Ten rodzaj testu, o którym Pan wspomniał, nie jest testem jednostkowym. Myślę, że to jest test integracyjny typu. Podczas pisania testu jednostkowego testujesz klasę ze wszystkimi wyodrębnionymi zależnościami. Używanie prawdziwej bazy danych (nawet baz danych w pamięci) w testach jednostkowych jest nieprawidłowe. –

+0

To nie jest pełny test integracji. Jest ważny! To po prostu nie jest test jednostkowy. – Gilberto

Odpowiedz

16

Możesz spróbować mockito. Test działa w następujący sposób:

Używasz mockito do "realizacji" EntityManager. Zamiast prawdziwego kodu, używasz metod mockito, aby powiedzieć "jeśli aplikacja wywoła getReference(), a następnie zwróci ten obiekt". W tle mockito utworzy instancję proxy, która przechwyci wywołania metod Java i zwróci podane przez ciebie wartości. Połączenia z innymi metodami powrócą null.

szyderczy rzeczy jak createQuery() działa w ten sam sposób, ale trzeba najpierw stworzyć makieta Query a następnie użyć tego samego podejścia jak w getReference() (powrót makieta zapytań).

Ponieważ nie używasz prawdziwego EM, nie potrzebujesz prawdziwego persistence.xml.

O wiele prostszym rozwiązaniem byłoby ustawienie właściwości w celu zmiany nazwy pliku persistence.xml, ale nie sądzę, aby było to możliwe.

Niektóre inne linki, które mogą pomóc:

+0

Przyjrzałem się używaniu obiektów Mock (zrobiłem to dla testów opartych na LDAP) i jest to z pewnością opcja. W tym konkretnym przypadku chciałbym faktycznie zapytać DB, aby potwierdzić rzeczy end-to-end, a nie tylko upewnienie się, że moje DAO zwraca informacje. – mlaccetti

+2

W takim przypadku istnieje rozwiązanie w pierwszym łączu: Możesz określić kilka "jednostek trwałości" w pliku persistence.xml i wybrać inny w swoich testach jednostkowych. –

4

Używamy podwójne persistence.xml pliki czasy pracy produkcyjnych i testowych, ale to tylko kwestia związana classpath (używamy Eclipse, ale nie polegamy na wtyczkach WTP). Jedyna różnica między nimi polega na tym, że wersja produkcyjna nie zawiera definicji jednostek.

Nie używamy szyderczego schematu do testowania JPA, ponieważ nie zwiększyłoby to wartości naszych testów. Testy uruchamiają rzeczywisty dostęp do danych za pomocą JPA, który komunikuje się z bazą danych PostgreSQL.

Nasze podejście do testów opiera się na wiosennym modelu testowym dla warstwy trwałości: testowanie w trakcie transakcji. Nasza aplikacja jest oparta na wiosennej wersji, ale to podejście jest równie przydatne dla dowolnych aplikacji, które chcą skorzystać z wiosennych klas testowych. Istotą jest to, że każdy test jest uruchamiany w ramach jednej transakcji, która nigdy nie zostanie zatwierdzona, a na końcu (w tearDown) zostanie automatycznie wycofana. Rozwiązuje to problem zanieczyszczenia danych i zależności testowych w bardzo miły, dyskretny i przejrzysty sposób.

Wiosenne ramy testowe są elastyczne, aby umożliwić testowanie wielu transakcji, ale są to specjalne przypadki, które stanowią nie więcej niż 10% testów.

Nadal używamy legacy support for JUnit 3.8, ale nowy Spring TestContext Framework dla JUnit 4 wygląda bardzo atrakcyjnie.

Do konfigurowania danych testowych w transakcjach używamy własnej klasy narzędziowej, która tworzy jednostki biznesowe. Ponieważ jest on dzielony na wszystkie testy, koszty ogólne utrzymania i obsługi są znacznie niższe dzięki korzyściom wynikającym ze standardowego i niezawodnego sposobu konfigurowania danych testowych.

Wiosny DI pomaga sprawić, by testy były zwięzłe i samoopisowe, ale nie jest to funkcja krytyczna.

+0

Używam JUnit 4.x (4,6, w końcu liczę, jak sądzę) i rozszerzenia testów wiosennych. Pomagają wspaniale w tworzeniu środowiska JPA, ale nadal mam problemy, ponieważ moja produkcja persistence.xml odwołuje się do WEB-INF/lib/common-code.jar, co nie działa dobrze z testowaniem. – mlaccetti

4

Korzystanie z testów jednostkowych Spring and Spring to najlepszy sposób na pokonanie. Ze sprężyną nie potrzebujesz dwóch plików persistence.xml, ponieważ twój plik persistence.xml nie zawiera niczego, wszystko jest określone przez sprężynę (wszystko, co określamy w naszym pliku persistence.xml to nazwa jednostki trwałości), co umożliwia zmianę konfiguracji bazy danych itp. ze sprężyną.

I jak wskazał topchef, testowanie jednostkowe oparte na transakcjach wiosennych jest świetne.

+0

W jaki sposób określić, które klasy załadować i jakie słoiki wykopać kod na wiosnę? Wydaje mi się, że przegapiłem coś ważnego. – mlaccetti

+0

Używam OpenJPA, która wymaga -javaagent włączone w środowisku wykonawczym i używa persistence.xml. W jaki sposób powinienem powiedzieć agentowi OpenJPA, aby szukał wśród klas wspomnianych w konfiguracji wiosennej, a nie w pliku persistence.xml? –

+0

hmmm ... Myślę, że ta odpowiedź jest może trochę nieaktualna. Musisz określić w swoim persistence.xml listę twoich trwałych klas –

0

Jak wspomniano tutaj: http://www.devx.com/java/Article/36785/1954, można usunąć następujące wiersze z projektu .settings/org.eclipse.wst.common.component, aby uniknąć wdrażania zasobów testowych w aplikacji internetowej.

<wb-resource deploy-path="/WEB-INF/classes" source-path="/src/test/java"/> 
<wb-resource deploy-path="/WEB-INF/classes" source-path="/src/test/resources"/>