Du verwendest einen veralteten Browser. Es ist möglich, dass diese oder andere Websites nicht korrekt angezeigt werden. Du solltest ein Upgrade durchführen oder ein alternativer Browser verwenden.
Ich gehe mal davon aus, dass du JPA verwendest. Persistence Injection funktioniert bei JUnit-Tests nicht,
daher muss man den EntityManager selbst erzeugen bzw. eine getrennte persistence.xml, speziell für Tests,
erzeugen und diese in Tests verwenden. Am besten erstelle ein getrenntes Projekt, in dem nur JUnit-Tests
enthalten sind.
Hier ein Beispiel (Hibernate als JPA Implementierung)
persistence.xml für den Serverbetrieb (DS über JNDI)
@Stateless
@Local(...)
public class BankingFacade implements ...
{
private static final long serialVersionUID = ...;
@PersistenceContext( unitName = "OraclePU" )
private EntityManager entityManager;
public BankingFacade()
{
}
/**
* Setter für EntityManager. Diese Methode wird nur in der Testumgebung benötigt.
*
* @param entityManager EntityManager aus der Testumgebung
*/
public void setEntityManager( EntityManager entityManager )
{
this.entityManager = entityManager;
}
...
Abstrakte Implementierung einer Testklasse. Stellt EntityManager zur Verfügung
Was Semi geschrieben hat, tönt gut... ich mach es aber so, dass ich die JUnit als Client laufen lasse und so über RMI von aussen auf den Server zugreife... leider muss man heirführ wirklich eine Testinstance am laufen haben, was recht mühsam sein kann. Aber das Mit den EJBtest was du geschrieben hast mache ich nicht.
Danke für Eure guten Ideen! Wird morgen ausprobiert!
@ semi:
Das sieht ziemlich gut aus (bin gespannt auf das Ausprobieren) - bist Du da selbst drauf gekommen oder steht das in irgendeinem Buch?
@ boxi:
Auch interessant, aber das klappt doch nur für den Unit-Test der Methoden, die im Interface definiert sind, oder? Wenn ich auch noch eine kleine Helper-Methode unit-testen möchte, die nicht im Interface definiert ist, dann geht's nicht mit Deiner Idee, oder habe ich da etwas falsch verstanden?
Ich finde das trotzdem ziemlich genial, zumal selbst im 500-Seiten-EJB3-Wälzer von Bill Burke nichts über das Testen steht. Man muss da erstmal drauf kommen.
Und andere JNDI-Ressourcen? Wie mockst Du die? Man kann doch eigentlich alles, was mit @EJB, @Ressource etc. annotiert wird, ebenfalls über den Aufruf von Settern aus der JUnit-Klasse heraus lösen, oder?
Und andere JNDI-Ressourcen? Wie mockst Du die? Man kann doch eigentlich alles, was mit @EJB, @Ressource etc. annotiert wird, ebenfalls über den Aufruf von Settern aus der JUnit-Klasse heraus lösen, oder?
Sowas mache ich nicht. Ich gehe zunächst mal davon aus, dass diese Mechanismen funktionieren und nicht getestet
werden müssen (Jede Katastrophe beginnt mit einer Vermutung ). Das ganze aus dem Grund, dass ich Facaden,
Webservices etc. nie mit irgendwelcher Anwendungslogik versehe. Die Dinger sind einfache "Schleusen" für die
dahinter liegende Geschäftslogik, die eine Schicht weiter implementiert ist. Eine Facade beschränkt sich nur auf die
Weiterleitung des Aufrufs, Exception-Logging, Exception-Handling (z.B. Konvertieren serverseitiger Exceptions in
eine allgemeine Exception, nennen wir sie mal ServerException, die bis zum Client weitergereicht wird und nur ein
Minimum an Informationen enthält (Errorcode und übersetzte Fehlermeldung).
Aber wenn ich es machen würde, dann vermutlich ähnlich wie mit der Facade (einfach einen Setter für die anderen
Ressourcen/EJBs etc.)
Alternativ auf die Ressourcen/EJBs über Getter zugreifen und diesen in einem Mock-Objekt überschreiben
Code:
public class BankingFacade ...
{
@EJB
private CustomerFacade customerFacade; // Eigentlich auch gaga. Facade in Facade ist etwas uncool.
... Constructore etc.
protected CustomerFacade getCustomerFacade()
{
return customerFacade;
}
public void tueWasAuchImmer()
{
...
// Nie direkt auf customerFacade zugreifen, sondern immer über die Getter-Methode
getCustomerFacade().tueWasAuchImmer();
...
}
}
public BankingFacadeMock extends BankingFacade implements ...
{
private CustomerFacade customerFacade;
protected CustomerFacade getCustomerFacade()
{
if(customerFacade == null)
{
customerFacade = new CustomerFacadeMock();
customerFacade.setEntityManager(getEntityManager());
}
return customerFacade;
}
}
Nachteil der zweiten Methode ist, dass man die ganzen Mock-Klassen implementieren muss.
Viel Getippe ohne irgendeinen erkennbaren Vorteil.
Okay... dann muss ich nun erstmal ausprobieren, ob der in die SessionBeans injizierte EntityManager auch in "normalen" Klassen im AppServer funktioniert, also ob man aus der SB "normaleKlasse.tuEtwas(entityManager)" aufrufen kann. Da bin ich mir nicht sicher...
Hätte noch einen kleinen Verbesserungsvorschlag für Deinen coolen AbstractTestCase. Habe in meine persistence.xml das automatische Generieren und wieder Aufräumen des DB-Schemas aufgenommen. Das Aufräumen klappt aber nur, wenn nicht nur der EntityManager, sondern auch die EntityManagerFactory am Ende geschlossen wird (was darauf hindeutet, dass man ansonsten etwas unsauber aus dem TestCase geht :wink: ):