Erste Schritte TDD testen einer Methode mit injezierten Services?

lam_tr

Top Contributor
Hallo zusammen,

da ich jetzt wieder umfangreicher Test schreiben muss, habe ich gleich von vorne herein eine Frage. Wenn ich eine Methode habe, die mehrere Services benutzen, wie im folgenden Code

Code:
public Result export(String exportPath){
...
Contact contact = contactService.findByName("Max", "Mustermann");
String name = userNameService.findUsernameBy(contact);
...
}

Wie kann ich den Rückgabewert der Methode contactService#findByName und userNameService#findUsernameByContact mocken? Damit die export Methode ein Ergebnis von Result zurückgibt? Bei dem Beispiel greifen die Services auf eine Datenbank und holen sich da die Werte, wie kann ich in mein Test diesen Datenbankzugriff mocken?

Kann ich das mit Mockito @mock und @InjectMock erreichen? Soweit ich es verstanden habe, kann man doch ein gemockte Klasse in ein andere gemockte Klasse verpacken oder? Wenn ich folgendes mache, würde es dann für das folgende Beispiel gehen? Was passiert denn mit der Datenbankzugriff?

Code:
@Mock
ContactRepository contactRepository

@InjectMock
ContactService contactService

Grüße
lam
 
Zuletzt bearbeitet:

LimDul

Top Contributor
Der contactService und der userNameService sind ja vermutlich private Fields in deiner Klasse.

Schritt 1:
* Es muss möglich sein, in Tests diese Felder mit Instanzen zu versehen, die nicht den Original-Instanzen entsprechen. Wie genau das am besten geht, hängt stark von der verwendeten Technologie (Spring Boot, CDI, Plain Java, etc.) ab. Die einfachste Möglichkeit ist, dass es einen Konstruktor gibt, der Instanzen dieser Klassen entgegen nimmt, Beispiel:

Java:
public class MyClassZuTesten {

public MyClassZuTesten(ContactService contactService, UserNameService userNameService) {
  this.contactService = contactService;
  this.userNameService = userNameService;
}

Dann kannst du einfach im Test mit Mockito arbeiten (hier mal alles in eine Test-Methode gepackt, in der Regel wird man den Setup-Code auslagern)

Java:
public void testMeineMethode() {
ContactService contactService = Mockito.mock(ContactService.class);
UserNameServer userNameService = Mockito.mock(UserNameService.class);

MyClassZuTesten meineKlassen = new MyClassZuTesten(contactService, userNameService);
Contact testContact = new Contact();
Mockito.when(contactService.findByName(Mockito.anyString(), Mockito.anyString()).thenReturn(testContact);
}
 

lam_tr

Top Contributor
Der contactService und der userNameService sind ja vermutlich private Fields in deiner Klasse.

Schritt 1:
* Es muss möglich sein, in Tests diese Felder mit Instanzen zu versehen, die nicht den Original-Instanzen entsprechen. Wie genau das am besten geht, hängt stark von der verwendeten Technologie (Spring Boot, CDI, Plain Java, etc.) ab. Die einfachste Möglichkeit ist, dass es einen Konstruktor gibt, der Instanzen dieser Klassen entgegen nimmt, Beispiel:

Java:
public class MyClassZuTesten {

public MyClassZuTesten(ContactService contactService, UserNameService userNameService) {
  this.contactService = contactService;
  this.userNameService = userNameService;
}

Dann kannst du einfach im Test mit Mockito arbeiten (hier mal alles in eine Test-Methode gepackt, in der Regel wird man den Setup-Code auslagern)

Java:
public void testMeineMethode() {
ContactService contactService = Mockito.mock(ContactService.class);
UserNameServer userNameService = Mockito.mock(UserNameService.class);

MyClassZuTesten meineKlassen = new MyClassZuTesten(contactService, userNameService);
Contact testContact = new Contact();
Mockito.when(contactService.findByName(Mockito.anyString(), Mockito.anyString()).thenReturn(testContact);
}
Und was ist wenn ich die Services meinen Exporter nicht als Konstruktor Parameter übergeben kann? Außerhalb der Klasse zu mocken und nicht zu übergeben ist nicht möglich? Die Services werden über Dependency Injection geholt, aber ich will die Datenbankzugriffe vermeiden.

Meine TestKlasse muss irgendwie die zwei Instanzen der Services kennen. Aber wie weiß ich noch nicht.
 

LimDul

Top Contributor
Das hängt von deinem Framework ab. Du musst im Test dafür sorgen, dass Dependency Injection Framework bei der Anfrage die zwei Testinstanzen liefert und nicht die normalen. Das ist Framework spezifisch.

Man kann für sowas aber oft auch einen protected oder package private Konstruktor vorsehen (neben dem Default-Konstruktor für das DI), der die übergeben bekommt. Hängt aber auch davon ab, wie man den zu testenden Service im Test instanziert.
 

lam_tr

Top Contributor
Ich benutze hier Google Guice für DI und auch sozusagen mein Problem, da ich nicht genau weiß wie ich meine zwei Services der Testklasse reichen kann.

Macht man extra einen neuen Konstruktor nur für Tests?
 

LimDul

Top Contributor
Ja. Aber wie das mit deinem DI Framework zusammenarbeitet ist die Frage.

Du hast dann zwei Sachen, die per Reflection Felder setzen - Mockito und das DI Framework. Wer gewinnt, kann ich dir aus dem Bauch heraus nicht sagen.

Wir diskutieren hier auf einer sehr abstrakten Ebene und ich hab das Gefühl, du weißt noch gar nicht genau, was Mockito eigentlich macht.

Vielleicht würde ein konkretes Beispiel von dir mal helfen um das etwas konkreter zu machen. Den mir ist aktuell absolut unklar, wie du im Test dein Objekt konkret erzeugt. Per new kann es ja nicht sein, sonst würde das DI-Framework nicht greifen.
 

lam_tr

Top Contributor
Ja. Aber wie das mit deinem DI Framework zusammenarbeitet ist die Frage.

Du hast dann zwei Sachen, die per Reflection Felder setzen - Mockito und das DI Framework. Wer gewinnt, kann ich dir aus dem Bauch heraus nicht sagen.

Wir diskutieren hier auf einer sehr abstrakten Ebene und ich hab das Gefühl, du weißt noch gar nicht genau, was Mockito eigentlich macht.

Vielleicht würde ein konkretes Beispiel von dir mal helfen um das etwas konkreter zu machen. Den mir ist aktuell absolut unklar, wie du im Test dein Objekt konkret erzeugt. Per new kann es ja nicht sein, sonst würde das DI-Framework nicht greifen.
:) Ja dein Gefühl hat dir das richtige gesagt, ich bin sehr neu in Mockito und versuche es anhand eines praktischen Test zu verstehen.

Ich schau mal ob ich das abgebildet bekomme, dann stelle ich den Code vor.

Danke.
 

LimDul

Top Contributor
Kleine Anmerkung am Rande, TDD ist das nicht. Bei Test Driven Development würdest du zuerst die Tests schreiben - und durch die Tests gibst du eine API vor, so dass die Klasse testbar ist. Wenn du schon Code hast und nachträglich Tests schreibst, ist es nicht mehr test-driven :)
 

lam_tr

Top Contributor
Ja danke für die Begrifflichkeiten :)

Eine weitere Frage. Ich weiss nicht wie schön dass ist, aber an sich kann ich anstatt die Services im Konstruktor zu übergeben auch direkt als Feld initialisieren?

Code:
@Mock ContactListExporter underTest;

public void testMeineMethode() {
underTest.contactService = mock(IContactService.class);
underTest.usernameService = mock(IUsernameService.class);
underTest.export();
}

So lässt es auch machen, aber wäre diese Weg in Ordnung?
 

mrBrown

Super-Moderator
Mitarbeiter
Naja, du müsstest dafür ein nicht-privates, veränderliches Feld haben. Fände sich sehr unschön, vor allem bietet es ja auch keinerlei Vorteile gegenüber einem vernünftigem Konstruktor, nur Nachteile.


Abgesehen davon willst du doch die Klasse unter Test eben nicht Mocken – Testen willst du doch die echte Implementation deiner Klasse.
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
H OOP Testen einer Exception mit JUnit Allgemeine Java-Themen 8
A AVL-Baum - Testen ob einer vorliegt Allgemeine Java-Themen 4
S Testen einer Anwendung durch klicken von Koordinaten Allgemeine Java-Themen 7
K Testen einer Klasse mit File Objekt als Parameter Allgemeine Java-Themen 6
Zrebna Zuverlässiges Automatisiertes Testen im eigenem Software-Unternehmen aufsetzen - How to? Allgemeine Java-Themen 12
Zrebna Automatisiertes Testen von größeren und komplexen Prozessen Allgemeine Java-Themen 56
Z Testen ob neuer Tag beginnt Allgemeine Java-Themen 37
S Habt ihr eine Idee wie man Serializierung testen kann..? Allgemeine Java-Themen 6
B Eclipse WebSocket programmiert, kann es leider nicht testen. Allgemeine Java-Themen 15
perlenfischer1984 TestNG - Enum testen Allgemeine Java-Themen 1
perlenfischer1984 Testng : Funktion mit mehreren Parametern testen Allgemeine Java-Themen 5
J Best Practice Testen von protected Methoden Allgemeine Java-Themen 7
F Testen von Methoden Allgemeine Java-Themen 3
B JUnit Zufalls Operation testen Allgemeine Java-Themen 1
P Testen von UIs Allgemeine Java-Themen 2
T MEthodenauruf testen, wenn instanz erst erzeugt wird Allgemeine Java-Themen 0
M Testen von verschiedenen Produktversionen Allgemeine Java-Themen 3
T EventBus testen Allgemeine Java-Themen 1
L JUnit - automatisiertes vs. manuelles Testen? Allgemeine Java-Themen 6
R Java Performance testen Allgemeine Java-Themen 18
B Mails testen Allgemeine Java-Themen 7
aze JUnit: Testen ob bestimmte Exception nicht auftritt Allgemeine Java-Themen 18
J JUnit - werfen von Exceptions testen Allgemeine Java-Themen 17
X Testen ob ein array leer ist Allgemeine Java-Themen 6
M Server-Responds testen, Code-Redundanz Allgemeine Java-Themen 3
fastjack Unit-Testen mit Mocks Allgemeine Java-Themen 6
B FileWriter / FileReader testen / Mock-Objekt für Unit Tests? Allgemeine Java-Themen 6
H Thread Safety und Deadlocks testen Allgemeine Java-Themen 6
D Muss eine JNI Biblio testen (MAC OS X) Allgemeine Java-Themen 4
T Object auf Double, Int, String testen Allgemeine Java-Themen 5
aokai Testen von Klassen die abhängig von Stdlibs URL sind Allgemeine Java-Themen 3
R Testen von Applets - versch. Browser und Java Versionen? Allgemeine Java-Themen 4
V Quellcode auf "Güte" testen? Allgemeine Java-Themen 5
G JAR-DAtei testen Allgemeine Java-Themen 15
J Klasse auf Konstruktor oder Methode testen? Allgemeine Java-Themen 3
A Junit Exceptions testen Allgemeine Java-Themen 3
Z Testen welches BS benutzt wird Allgemeine Java-Themen 3
G Testen von RMI,TCP/IP, Servlets etc. Allgemeine Java-Themen 2
M Welches Linux zum Java testen? Allgemeine Java-Themen 5
P Testen mit JUnit Allgemeine Java-Themen 8
L Java6 update N bekommt neues Browser-Plugin, bitte testen. Allgemeine Java-Themen 7
G testen mit JUnit? Allgemeine Java-Themen 3
K Testen ob Methode existiert? Allgemeine Java-Themen 2
N Cashbook Management Testen Allgemeine Java-Themen 7
A testen ob Primzahl dauert bei größeren zahlen extrem lange Allgemeine Java-Themen 8
M String testen? Allgemeine Java-Themen 2
M String testen? Allgemeine Java-Themen 6
N auf typ testen? Allgemeine Java-Themen 3
M Programmierstill: Bitte testen anhand HTML-Tool Allgemeine Java-Themen 18
M Bitte Testen: Mein Multi-File Editor Allgemeine Java-Themen 30
T GUI Testen Allgemeine Java-Themen 4
T GUI Testen Allgemeine Java-Themen 5
G Programm zum Testen der Striktheit von Java Allgemeine Java-Themen 9
H Laufwerk testen? Allgemeine Java-Themen 12
F Hilfe: Adjazenzmatrix mittels JUnit testen. Allgemeine Java-Themen 2
M Jemannd mit 1.4/1.3/1.2 zum Testen gesucht. Allgemeine Java-Themen 15
flashfactor Testen ob ein R/3 erreichbar bzw. noch am leben ist. Allgemeine Java-Themen 2
T Datum testen und Einsetzten Allgemeine Java-Themen 5
M Regular Expression - verschiedene Ausdrücke testen (grep | ) Allgemeine Java-Themen 5
P Dateinamen mit regulärem Ausdruck testen Allgemeine Java-Themen 9
P Dateinamen testen? Schreibrechte auf Verzeichnis testen? Allgemeine Java-Themen 8
O Text aus einer Textdatei rausholen, der zwischen zwei Schlüsselworten steht Allgemeine Java-Themen 4
V Umgang mit fehlenden Daten in einer Java-Datenanalyseanwendung Allgemeine Java-Themen 5
M Methodenübersicht einer Klasse einsehen Allgemeine Java-Themen 14
T JNA, Aufruf der Funktionen einer dll Allgemeine Java-Themen 5
I Vom Monolith zu Services in einer Webseite Allgemeine Java-Themen 1
W Variable Initialisierung mit dem Ergebnis einer Regex Allgemeine Java-Themen 1
O Werte einer Generic LinkedList zusammenrechenen Allgemeine Java-Themen 14
C Sortieren und Selektieren einer ArrayList<Point3D> Allgemeine Java-Themen 6
A Einzelne Objekte und Unterobjekte einer ArrayList ausgeben Allgemeine Java-Themen 53
TheSepp Wie kann man Leerzeichen aus einer Array liste entfernen? Allgemeine Java-Themen 10
B Ein Objekt einer Klasse mehreren anderen Klassen zur Verfügung stellen? Allgemeine Java-Themen 6
M Optimierung einer Methode (byte-Geraffel) Allgemeine Java-Themen 2
I Wie kann ich den Wert aus einer If abfrage ausgeben Allgemeine Java-Themen 23
S HTML einer Webseite 1:1 so bekommen wie es auch der Browser anzeigt? Allgemeine Java-Themen 14
melaniemueller Einzelne Zeile aus einer txt Datei in einem String speichern Allgemeine Java-Themen 12
L Java überprüfen lassen, ob sich ein gegebener Pfad / das Programm an sich auf einer CD oder Festplatte befindet Allgemeine Java-Themen 14
J (Geplante) Änderungen an einer Datei vorübergehend speichern und anwenden? Allgemeine Java-Themen 12
ME2002 Fragen aus einer Java Klausur Allgemeine Java-Themen 67
_user_q Obfuscate einer .jar-Datei mit ProGuard? Allgemeine Java-Themen 2
_user_q Verknüpfung einer .jar-Datei (liegt z. B. auf dem Desktop) im Autostart-Ordner erstellen? Allgemeine Java-Themen 20
C Parsen einer sich updatenden Html mithilfe von jsoup Allgemeine Java-Themen 4
E Eine Methode einer extendeten Klasse deakitivieren Allgemeine Java-Themen 12
H Performance einer Monte-Carlo-Simulation verbessern Allgemeine Java-Themen 6
LimDul Kam eine java.net.URL zu einer HashMap und ging als DNS Anfrage wieder heraus Allgemeine Java-Themen 18
E Variablen Nach Übergabe einer Variable den Constructor aufrufen Allgemeine Java-Themen 16
Zeppi NullPointerException in einer if-Abfrage Allgemeine Java-Themen 6
D Abbruch einer ViewScoped Bean in Arbeit Allgemeine Java-Themen 2
Lukas2904 Schleife mit ansteuerung einer Klasse Allgemeine Java-Themen 5
d.lumpi Aus Einer Klasse auf ein Objekt einer anderen Klasse Zugreifen Allgemeine Java-Themen 1
Lukas2904 Wie kann man cps (ClicksPerSecond) in einer GUI anzeigen lassen? Allgemeine Java-Themen 4
O Produziert das Tool "jpackage" (ab JDK 14) .exe Dateien, die auf einer Zielumgebung ohne JRE lauffähig sind ?` Allgemeine Java-Themen 7
R Lambda Expression in einer Methode execute() aufrufen (execute() ist eine Methode aus dem funktionalen Interface Command) Allgemeine Java-Themen 5
Drachenbauer wie kann ich alle instanzen einer Klasse durchsehen, ohne, dass diese in einer Liste erzeugt wurden? Allgemeine Java-Themen 11
N BlueJ Implementation einer Analoguhr Allgemeine Java-Themen 0
O Formatierte String ausgabe bei vier Variablen in einer Zeile Allgemeine Java-Themen 1
N Speicherort einer Datei im Explorer ändern Allgemeine Java-Themen 8
O Datentypen Wie kann ich den Typ einer ArrayList abfragen ? Allgemeine Java-Themen 7
O Leerzeichen und Umlaute im Pfad einer Java Applikation machen Probleme Allgemeine Java-Themen 13
H Mehrere PNG-Files in einer Datei Allgemeine Java-Themen 9

Ähnliche Java Themen

Neue Themen


Oben