Ich habe kürzlich gesehen, dass Integrationstests ein Betrug von JB Rainsberger sind, und suche jetzt nach mehr Material zu diesem Thema. Ich muss sagen, ich bin schockiert darüber, wie viel wir falsch machen (dh Integrationstests, wenn wir Unit-Tests durchführen sollten), fasziniert von den von Rainsberger beschriebenen Konzepten, aber auch verwirrt darüber, wie man sie anwendet. Ich hätte gerne mehr der beschriebenen Kollaborations- und Vertragstests , weiß aber nicht, wo ich anfangen soll.
Die einzigen Dinge, die mir in den Sinn kamen, sind die 4 Fragen, die die Tests stellen müssen:
Seite A:
Do I ask the right question?
Can I deal with the answer?
Seite B:
Can I answer a question?
Do I answer correctly?
Aber wie wende ich dies auf eine zufällige Methode in meinem Anwendungsstapel an?
Gibt es da draußen ein Buch, ein Tutorial oder ein Beispiel, das ein Beispiel aus der Praxis nimmt und diese Ideen isolierter Mikrotests anwendet? Idealerweise verwendet das Beispiel Java, Spring + PowerMock / Mockito / EasyMoock
Jede Literatur, die sich allgemein mit diesen Konzepten befasst und mir hilft, sie besser zu verstehen, wäre willkommen.
Auch wenn es Foren gibt, in denen ich detailliertere Fragen dazu stellen kann, wie man Unit-Tests korrekt durchführt und vielleicht sogar vorhandenen Code überarbeitet und Beispiele postet, wäre das nett.
Vielen Dank!
Bearbeiten - einige zusätzliche Gedanken:
Gibt es eine allgemeine Regel, wann ein Mock verwendet werden soll und wann ein Stub, um eine zu testende Klasse von ihren Mitarbeitern zu isolieren? Kann es auf die 4 Fragen angewendet werden?
Das beste Verspottungs-Framework scheint PowerMock zu sein, mit dem ich für jeden Test genau definieren kann, welche Klasse ich verspotten möchte und was sie zurückgeben soll, oder gibt es etwas Besseres, mit dem Sie die obigen Fragen gestellt haben? Gibt es gute Tutorials, die PowerMock verwenden, um einige oder alle der angegebenen Prinzipien auf einen Teil eines realen Anwendungsstapels anzuwenden, beispielsweise ein DAO oder eine GUI?
Edit 2 - ein Beispiel
Nur ein Beispiel für die Art von Methoden, die ich testen möchte, und meine Gedanken.
Ich habe einen Webservice, der Bestellungen speichert. Zu diesem Zeitpunkt sind wir nicht allzu besorgt über die beste Sicherheit. Um einige zu haben, benötigt der Dienst auch einen Benutzernamen und ein Kennwort, um die Speicheranforderung zu authentifizieren. Nach der Authentifizierung wird der OrderManager
aufgerufen, um das zu speichern Order
. Intern entscheidet der Manager, ob es sich um eine neue Bestellung handelt, die erstellt werden muss, oder ob eine vorhandene Bestellung aktualisiert werden muss. (Das sollte für WebSerice keine Rolle spielen, oder?)
@WebService
public class OrderService {
@Inject
private AuthenticationManager authenticationManager;
@Inject
private OrderManager orderManager;
public void save(String username, String password, Order order) {
authenticationManager.authenticate(username, password);
try {
orderManager.save(orde);
} finally {
authenticationManager.logout();
}
}
Jetzt frage ich mich: Was genau teste ich hier? Ich denke, es sollte Tests für Erfolg und Misserfolg der Authentifizierung und für Erfolg und Misserfolg beim Speichern von Aufträgen geben.
Aber wie kann ich das in die 4 Fragen aufteilen? Meine Klasse unter Test ist offensichtlich OrderService
(OS) und die Mitarbeiter sind OrderManager
(OM) und AuthenticationManager
. (AM) Also ich habe die folgenden Tests, bitte korrigieren Sie mich hier, ich denke nur laut:
OS <--> OM
- Das Betriebssystem fordert OM auf, eine Bestellung zu speichern (welche unterschiedlichen Parameter teste ich hier?
null
UndOrder
? Ist es wichtig, ob sieOrder
korrekt initialisiert sind?) - OM beantwortet einen Sicherungsaufruf, indem es eine andere interne Methode aufruft. II Test, ob diese Methode aufgerufen wird?!
- Das Betriebssystem sollte nicht ausfallen, wenn OM nicht ausfällt
- Das Betriebssystem sollte ausfallen, wenn OM ausfällt
... Was sonst?
Und dann natürlich OS <--> AM :
- OS bittet AM um Authentifizierung - Ich schätze, ich teste, wie der AM auf verschiedene Arten von Benutzernamen / Passwort reagiert.
- ...
Nun meine erste Schlussfolgerung :
Soweit der WebSerice angeht kann ich nur 2 testen von 4 Fragen: Side A. Jetzt muss ich bei der Suche OrderManager
und AuthenticationManager
sehen , ob sie die Fragen der Seite B. Rechts beantworten kann?
Zweitens - Datenbankzugriff:
Die Authentifizierung und das Fortbestehen der Bestellung erfordern offensichtlich einige Daten in der Datenbank in einer Produktionsumgebung. Für meine Unit-Tests brauche ich sie jedoch nicht, also verspotte ich nur die Anrufe, um das gewünschte Ergebnis zurückzugeben, oder? Aber wie verspotte ich das?
Ich brauche AuthenticationManager.authenticate
so ziemlich nichts zu tun, da im Falle einer fehlgeschlagenen Authentifizierung eine ausgelöst wird Exception
, sonst hat es den Rückgabetyp void
. Wie sage ich meinem OrderService.save()
, ich soll mein verspottetes benutzen AuthenticationManager.authenticate()
?
Und wie richte ich das Setup AuthenticationManager
so ein, dass es entweder nichts tut oder eine Ausnahme auslöst?
Kann ich Spring anweisen, einen Verspotteten zu injizierenAuthenticationManager
, der nichts bewirkt / einen Exception
in meinen OrderService
Test wirft ?