Erste Schritte TDD testen einer Methode mit injezierten Services?

L

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:
L

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);
}
 
L

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.
 
L

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.
 
L

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?
 
L

lam_tr

Top Contributor
Wie funktioniert das dann mit @mock und @InjectMock, ist es nicht ein gemocktes Object in ein anderes gemocktes Object?
 
L

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.
 
L

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.
 
L

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 :)
 
L

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

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
ZeusSeinGrossopa 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 3
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
L RegEx für Teile einer Berechnung Allgemeine Java-Themen 14
J Zerlegen einer Zahl Allgemeine Java-Themen 6
Zrebna Wie kann man endgültig aus einer Rekursion ausbrechen? Allgemeine Java-Themen 14
M Person in einer Arraylist hinzugügen mit Prüfung ? Allgemeine Java-Themen 6
Meeresgott Effizientester Weg um nach der Value einer verschachtelten Map aufzulösen Allgemeine Java-Themen 5
H Mehrere Datentypen in einer Arraylist speichern Allgemeine Java-Themen 9
M Prüfziffer einer EAN Nummer berechnen Allgemeine Java-Themen 4
M Erstellungsdatum einer Datei Allgemeine Java-Themen 10
Drachenbauer Wie kann ich einer existierenden Enum von außerhalb veränderte Werte zuweisen? Allgemeine Java-Themen 5
S HTML den ich von einer URL hole nicht identisch mit dem HTML im Browser Allgemeine Java-Themen 1
S Rückgabe einer HttpURLConnection für eine Seite einlesen bei der man eingeloggt ist..? Allgemeine Java-Themen 5
O Java-Applikation tut in Netbeans, als JAR nicht, wegen Pfadangaben einer benötigten Datei Allgemeine Java-Themen 8
M Hilfe bei einer Java Programmieraufgabe! Ab morgen Montag um 08:00 Uhr Allgemeine Java-Themen 5
J Algorithmen Analyse einer Schleife Allgemeine Java-Themen 6
Drachenbauer Wie finde ich den Aufrufer zu einer Methode, die sich nicht in meinem Projekt befindet? Allgemeine Java-Themen 2
J Die Letzte Zahl aus einer Text datei lesen Allgemeine Java-Themen 8
P einen public <Optinal String> in einer anderen Klasse mit einem Int vergleichen Allgemeine Java-Themen 2
A Mithilfe von einer Nummer einen Namen finden n-Beziehung Allgemeine Java-Themen 8
Scream_ilias Auf einer Website die anmeldedaten eingeben Allgemeine Java-Themen 9
V Threads Probleme beim Aufrufen von Methoden einer anderen Klasse (Threads) Allgemeine Java-Themen 14
I Lohnt sich heutzutage der Aufwand einer Portierung für MacOS Allgemeine Java-Themen 8
J Suchen von einer Scannereingabe in einem HashSet Allgemeine Java-Themen 1
M Konstruktor einer Methode Allgemeine Java-Themen 35
L Echtzeitdaten aus einer Webseite ziehen mit Java Allgemeine Java-Themen 19
V EMail, Attachments auslesen von einer Email Allgemeine Java-Themen 0
T Google Links in einer Liste Allgemeine Java-Themen 4
T Sinn einer toString Methode Allgemeine Java-Themen 3
P Durchlaufen einer Queue Allgemeine Java-Themen 9
J Größe einer CD ermitteln Allgemeine Java-Themen 10
L Operatoren Java Reflections: Alle Methoden einer Klasse aufrufen ohne Exceptions Allgemeine Java-Themen 5
H Länge einer verketteten Liste Allgemeine Java-Themen 4
B Quellcode einer Java libary finden um zu copy & paste'n Allgemeine Java-Themen 5
N Daten einer JCoTable in JTextArea anzeigen Allgemeine Java-Themen 7
sascha-sphw Java 9 module Zugriff auf eine resource einer anderen JAR Allgemeine Java-Themen 0
N Generic Type einer Generischen Klasse während der Laufzeit bekommen Allgemeine Java-Themen 2
E Erstellen einer Liste mit einer maximalen Menge an Elementen Allgemeine Java-Themen 13
M Wie kann ich ein int[] Array in einer Methode benutzen? Allgemeine Java-Themen 6
T Compiler-Fehler NoClassDefFoundError beim Laden einer Class Allgemeine Java-Themen 11
H Klassen LibGDX - Verschiedene Klassen als Value in einer Map Allgemeine Java-Themen 8
P Element einer Liste wurde hinzugefügt, aber es gibt keinen Zugriff Allgemeine Java-Themen 2
E Elemente innerhalb einer ArrayList vergleichen Allgemeine Java-Themen 33

Ähnliche Java Themen

Anzeige

Neue Themen


Oben