Verständnisproblem beim Mocking

Saheeda

Top Contributor
Hallo,

ich habe n Problem dabei zu verstehen, warum man mockt / welchen Sinn das Ganze hat.
Bisher habe ich zwei Arten von Tests dazu gesehen:

a) Prüfe, ob Funktion X überhaupt (oder nie, oder x-mal) aufgerufen wird und durchläuft.
b) Nimm an, dass die Funktion den Wert Z zurückliefert und prüfe, ob das auch so ist.

zu a) Welche Aussagekraft hat ein Test, der nur überprüft, ob eine Funktion überhaupt aufgerufen wird und sich nicht um die Auswirkung kümmert bzw die Funktion nichts Validierbares macht?
Ich kann prüfen, ob keine Exception fliegt, ja. Aber dass es nicht knallt, bedeutet ja noch lange nicht, dass alles so funktioniert, wie es soll.

zu b) Welchen Sinn hat es, ein Testergebnis zu überprüfen, das ich bereits vorher festlege?


Bisher sieht Mocking für mich so aus:
- Male das Haus rot an.
- Überprüfe, ob das Haus rot ist.
- Freu dich nen Keks, dass das Haus rot ist.
 
Mock-Objekte (auch Attrappe, von englisch to mock ‚etwas vortäuschen‘) sind in der Softwareentwicklung Objekte, die als Platzhalter für echte Objekte innerhalb von Modultests verwendet werden.

die eigentliche Idee dahinter ist, das du einen Test schreibst, der Festlegt wie sich dein richtiges Objekt später verhalten soll.
Danach kannst du dein eigentliches Objekt erstellen und auf deinen Test loslassen und schauen, ob das Objekt die Testkriterien erfüllt oder nicht.

Siehe auch Testgetriebene Entwicklung

edit::

Mock-Objekte können im übrigen auch Externe Quellen sein die du z.B. in einem Unit-Test nicht abbilden kannst da diese garnicht zur verfügung stehen

Objekt A kann seine Daten aus einer Datenbank laden und hat eine Methode "setDatenbank()"
Damit das Objekt im test jetzt nicht für jede Funktion "hey ich hab keine DB" rausgibt erzeugst du ein Mock-Objekt das so tut als wäre es die Datenbank und für die jeweiligen Funktionen Testwerte rausgibt
 
Zuletzt bearbeitet:
TDD ist mir klar.

Aber wenn ich zum Beispiel eine Methode doSomething() habe und nur überprüfe, ob keine Exception fliegt, dann kann in der Methode selbst auch zehntausend Mal "Du bist doof" stehen und der Test ist trotzdem grün.
 
du kannst ja auch mehr als nur prüfen ob "doSomething()" keine exception wirft. welchen rückgabetyp hat das ding, wie reagiert es auf sonderfälle (z.B. divide(double i, double j) mit divide(10d, 0d) aufrufen) usw usw.

und um zu deiner ursprünglichen Frage zurückzukommen:

ich rufe eine Funktion auf mit der signatur "int add(Integer val, Integer val2)" und diese ist wie folgt implementiert:
Java:
Integer add(val 1, val2)
{
    if (val1 == null) { return val2; }
    return val1+val2;
}
und dein nutzender code sieht wie folgt aus:

Java:
Integer val1 = null;
Integer val2 = 20;

Integer result = add(val1, val2);

jetzt kommt aber ein anderer developer an und ändert den code von "add(...) wie folgt:

Java:
Integer add(val 1, val2)
{
    if (val1 == null) throw new IllegalArgumentException("val 1 is null");
    return val1+val2;
}

dann bekommst du das nicht direkt mit, sondern erst wenn dein programm mit der iae gecrashed ist.
Der Unit-test der das ding prüft hätte aber (sofern er den fall abgedeckt hat) alarm geschlagen und du hättest reagieren können

edit:::

unit-tests bringen dir erst wirklich etwas, wenn du eine gewisse menge an code (10MB+) hast, und/oder in einem Team arbeitest.
Stell dir vor, du hast eine methode (die sehr komplex ist) und du hast etwa 5000 aufrufer. nun stellst du fest "mist, da ist ein bug drin in einem ganz speziellen sonderfall" dann passiert meistens folgendes:

"wenn ich das jetzt änder, mach ich möglicherweise 5000 stellen unbrauchbar"
"dann bau ich mir lieber nen workaround"

und nach gut 2 monaten besteht der code zu 30% workarounds

mit unit-tests wäre das so gelaufen:

"hmm, wenn ich das änder, mache ich möglicherweise 5000 stellen unbrauchbar"
"ändern wir das doch mal"
"hmmm, 3 unit-tests für funktion (2230, 2503 und 4612) schlagen fehl..."
"anpassungvon 2230, 2503 und 4612"

keine workarounds 🙂
 
Zuletzt bearbeitet:
@Lodoss

Warum/wie man Tests schreibst, ist mir klar.

Ich verstehe nur nicht, warum man bestimmte Klassen "faked" & welche Aussagekraft so ein Test dann noch hat.
 
@Lodoss

Warum/wie man Tests schreibst, ist mir klar.

Ich verstehe nur nicht, warum man bestimmte Klassen "faked" & welche Aussagekraft so ein Test dann noch hat.

Warum man Klassen faked?
Ich habe eine Klasse die eine Rechnung erstellt. Dazu braucht sie Preise, Rabatte usw.. dazu benutzt sie andere Klassen. Die Rabatt Klasse benutzt wieder einen Kundengruppen Service, da die Rabatte von Kunden abhängig sind, diese Klassen greifen evtl auf andere Spring Services zu, die wieder mit JPA auf eine Datenbank zugreifen usw..
aber das interessiert mich alles gar nicht, ich will nur wissen, wenn ich 100 € und 50 € und 10 % Rabatt habe, dass ähmn ja 135 € raus kommt. Deshalb fake ich die klassen die meine Rechnungsklasse benutzt und definiere, die Werte dich ich testen will.

Ich arbeite in einem Projekt, bis du da für die konkrete Rechnungs Position den Steuersatz hast, werden mehr als 10 Klassen aufgerufen, die unter umständen komplexe Regel Engines aufrufen und Datenbank Zugriffe machen. Da muss man Dinge faken, sonst werden die Unit Tests zu komplex.
 
Zuletzt bearbeitet:
@Ardauer

Wenn ich dich richtig verstehe, prüfst du "nur":
Wenn ich von Klasse X korrekte Daten zurückbekomme, wie reagiert dann meine zu testende Klasse A?
bzw.: Wenn x nur Mist zurückliefert, reagiert A dann entsprechend?
 
Ich versuchs mal anders:

du hast eine Roboterdrohne, die soll von Paris nach München fliegen können
Die Drohne ist normalerweise GPS gesteuert und macht daran die eigene Position fest
Die Drohne ist so konzipiert, das diese landet, sobald das GPS Signal nicht empfangen werden kann.

Wenn du jetzt die software testen willst, ohne das du die Hardware zur hand hast, dann macht es sinn der Software die Hardware vorzugaukeln. Ob diese korrekte oder inkorrekte Daten rausgibt... ist beides Interesssant. Es geht halt darum Messbar zu machen, wie sich die Software unter bestimmten bedingungen Verhält ohne das man diese replizieren muss, denn wenn du deine Software jetzt nicht grade auf nem Handy testest sondern auf einer "normalen" workstation, hast du kein GPS signal / sensor.

Man stelle sich vor, das ding bekommt eine "Selbstzerstörung"... willst du die mit Hardware ausprobieren? 😛
 
Zuletzt bearbeitet:
Du fakst nicht die Klasse die du testen willst, sondern Klassen, mit denen die zu testende Klasse arbeitet (Beispiel Datenbank wurde ja schon gesagt).

Somit kannst du zum Beispiel auch Fehler testen, die unter normalen Umständen nicht auftreten würden (Datenbank meldet: Tabelle nicht gefunden).

Ich denke auch, das Mocking in kleinen Umgebungen nicht soviel Sinn macht. Das wird erst in größeren System interessant.
 

Zurück
Oben