Unit Test - Abgänigkeit zur Datenbank isolieren

looparda

Top Contributor
Hallo, ich beschäftige mich gerade mit unit tests und finde keinen Ansatz für folgendes Problem:
Ein Parser soll einen Rezepttext in ein Rezept wandeln und zurückgeben.
Java:
public class Parser {
    public IRecipe parse(String text) {
        IRecipe recipe = IRecipe.getInstance();
        recipe.setTitle("Sample Title");
        recipe.add("Reis", 200, "g");
        return recipe;
    }
}

Java:
public interface IRecipe {
    static IRecipe getInstance() {
        return new Recipe(); // Recipe erbt von einer ORM-Library, alle Funktionen des Interfaces IRecipe machen Datenbank-Zugriffe in Recipe.
    }
    boolean saveIt();
    String getTitle();
    long getID();
    void setTitle(String title);
    void add(IRecipeIngredient recipeIngredient);
    void add(String ingredientName, int amount, String unitName);
    Map<IIngredient, Map<Integer, IUnit>> getIngredients();
}

Jetzt möchte ich jedoch den Parser testen:
Java:
@Test
public void theParsedRecipeHasProperIngredients() {
    final List<String> ingredientNames = exampleRecipe
        .getIngredients()
        .keySet()
        .stream()
        .map(iIngredient -> iIngredient.getName())
        .collect(Collectors.toList());

    the(ingredientNames).shouldContain("Reis");
}
Problem: recipe.setTitle() und recipe.add(), recipe.getIngredients() usw. greifen in der Implementierung in Recipe auf die Datenbank zu. Das möchte ich beim Testen nicht.
Mein Ansatz wäre: Ich muss IRecipe.getInstance(); so bauen, dass es einen Mock zurückgibt, wenn die Tests ausgeführt werden und die "normale" Implementierung wenn es sich nicht um einen Test handelt.
Wie gehe ich vor um die Abhängigkeit zur Datenbank zu isolieren?
 
Zuletzt bearbeitet:

looparda

Top Contributor
Ich könnte auch dem Parser ein Objekt vom Typ IRecipe übergeben, mit dem er arbeiten soll. (ich denke Dependency Injection). Jedoch ergibt diese Änderung allein an der Signatur keinen Sinn, bzw. sieht falsch aus.
Java:
public IRecipe parse(IRecipe recipe, String text)
Und vorher per Konstruktor übergeben? Weiß nicht. Brauche jemanden mit Erfahrung, der hilft.
 
Zuletzt bearbeitet:

mrBrown

Super-Moderator
Mitarbeiter
Du musst Interface und Implementation trennen, so wie es aktuell ist, ist das Interface ja an die Implemenation gekoppelt.

Ich würde würde statt der getInstance-Methode einen Builder benutzen, ggf mit Interface, der dem Pariser übergeben wird. In den Tests übergibt man dann einen anderen Builder, der eine IRecipe-Instanz ohne DB-Abhängigkeit erstellt.

Als Beispiel:

Java:
public interface IRecipeBuilder {
IRecipe getInstance();
}

public class DBRecipeBuilder {
@Override
IRecipe getInstance(){
       return new Recipe();
   }
} //Das gleiche für IRecipeImpl ohne DB-Abhängigkeit

public class Parser {
  private IRecipeBuilder builder; //Setzten über Setter,Konstruktor etc. oder erst über Methodenargument

   public IRecipe parse(String text /*,IRecipeBuilder builder*/){
        IRecipe recipe = builder.getInstance();
        recipe.setTitle("Sample Title");
        recipe.add("Reis", 200, "g");
       return recipe;
   }
}

In Programm und Tests übergibt man dann jeweils den passenden Builder.

Edit:

Andere Möglichkeit wäre, Perser abstrakt zu machen, darin eine abstrakte getInstance, fürs Programm wird das dann so implementiert, das IRecipe.getInstance benutzt wird, in den Tests gibts dann eine Test-Implementierung von IRecipe zurück
 

looparda

Top Contributor
Du musst Interface und Implementation trennen, so wie es aktuell ist, ist das Interface ja an die Implemenation gekoppelt.
Genau, es war so gedacht, die Referenz auf die konkrete Implementierung an genau einer Stelle ändern zu müssen, falls man später eine zweite Implementierung einführt, die benutzt werden soll. Leider war da noch nicht bedacht, dass ich dennoch eine 2. Implementierungen benötige für den Test.

Andere Möglichkeit wäre, Perser abstrakt zu machen, darin eine abstrakte getInstance, fürs Programm wird das dann so implementiert, das IRecipe.getInstance benutzt wird, in den Tests gibts dann eine Test-Implementierung von IRecipe zurück
Der Parser hat tatsächlich eine Abstrakte Klasse, die ich hier zur Vereinfachung weggelassen habe. Du meinst ich habe dann 2 Subtypen, jeweils normal und für Tests? Dies wäre auch mit einer protected und nur einem Subtypen möglich, der dann diese Funktion überschreibt und einen Fake zurückgibt. Jenes ist mir dann als Seam bekannt.
Ich denke ich versuche es mit dem Builder.
 
Zuletzt bearbeitet:
Ähnliche Java Themen
  Titel Forum Antworten Datum
W Checkliste Unit Test Allgemeine Java-Themen 17
R Unit Test Allgemeine Java-Themen 1
K Unit Test consolen ein-/ausgaben. Allgemeine Java-Themen 7
Y Wieso krieg ich die Unit Tests nicht hin Allgemeine Java-Themen 55
Y Wie sinnvolle unit tests schreiben Allgemeine Java-Themen 29
sascha-sphw Erste Schritte Unit und Integration-Tests im Java Modul System Allgemeine Java-Themen 10
B Frage zu Unit-Tests Allgemeine Java-Themen 6
J Alle Unit Tests in Maven Modul Projekt ausführen Allgemeine Java-Themen 7
M Für was schreibt man Unit-Tests? Allgemeine Java-Themen 55
P J-Unit vergleich von 2 Objekten merkwürdig Allgemeine Java-Themen 7
G ThreadLocal in Muster "Unit of Work" Allgemeine Java-Themen 7
M Html Unit Whitespace-Problem Allgemeine Java-Themen 4
fastjack Unit-Testen mit Mocks Allgemeine Java-Themen 6
Jay_030 Guice: Frage im Umgang mit Unit-Tests Allgemeine Java-Themen 4
B FileWriter / FileReader testen / Mock-Objekt für Unit Tests? Allgemeine Java-Themen 6
S Unit Testing mit JMock Allgemeine Java-Themen 11
alexpetri unit tests für pdfs Allgemeine Java-Themen 4
B J-Unit Tests. Alle Tests eines Package einsammen. Allgemeine Java-Themen 4
tfa Unit-Tests für private Methoden Allgemeine Java-Themen 25
W Unit Tests im "Hauptprojekt" oder in Modulen Allgemeine Java-Themen 3
M Eine Frage über Unit-Tests mit Java Allgemeine Java-Themen 2
N Ausgaben (System.out) umlenken und in Unit-Tests überprüfen? Allgemeine Java-Themen 2
Zrebna Wieso sind eigentlich JUnit-Tests in src/test/java platziert - nur Konvention? Allgemeine Java-Themen 7
M Archunit Test Allgemeine Java-Themen 0
O Test schreiben mit Äquivalenzklassen (Aufgabe Prüfung) Allgemeine Java-Themen 9
B Junit Test Allgemeine Java-Themen 8
P Karate API Test läuft nicht durch . initializationError Allgemeine Java-Themen 21
J Junit surefire: enrich test information Allgemeine Java-Themen 0
Gaudimagspam White-Box-Test /Glas Box Test Allgemeine Java-Themen 2
F Junit Test + Cucumber - JSON auslesen und in einem weiteren Schritt nutzen Allgemeine Java-Themen 0
M Test geht auf Travis und mit Github Action schief aber nicht lokal Allgemeine Java-Themen 3
S Test mit Werten aus der .properties Allgemeine Java-Themen 4
T Weighted QuickUnion Test Allgemeine Java-Themen 5
S Zugriff auf jUnit Test Suite Runner-Instanzen innerhalb von Test Classes Allgemeine Java-Themen 7
S Eclipse Probleme beim Implementieren / Ausführen von jUnit 5-Test Suites Allgemeine Java-Themen 14
S Parametrisierte jUnit 5-Tests mit eigenen Datentypen/Klassen-Objekten als Test-Parameter Allgemeine Java-Themen 0
S Eclipse TestNG Default Test umbenennen Allgemeine Java-Themen 0
F UI Test auf Jenkins Allgemeine Java-Themen 1
K Test-Frist Programmierung - wie vorgehen Allgemeine Java-Themen 5
E JUnit wie Testergebnisse pro Test ("Test Report") erhalten? Allgemeine Java-Themen 1
R Test Umgebung für Datenbank erstellen, was braucht es? Allgemeine Java-Themen 14
M JUnit Test Suites Allgemeine Java-Themen 2
B Hilfe bei JUnit Test Allgemeine Java-Themen 1
E YQL Api Test - NullPointer Allgemeine Java-Themen 9
B JUnit4 Exception-Test Allgemeine Java-Themen 4
A eine test thread.join() frage Allgemeine Java-Themen 2
P Klassen Junit test funktioniert nicht... Allgemeine Java-Themen 11
W Frage zu Klassendesign und Test mit Mockito Allgemeine Java-Themen 5
G JUnit Test Methoden in anderen Thread verlagern Allgemeine Java-Themen 4
J JUnit, TestCase vs "einfacher" Test Allgemeine Java-Themen 3
1 JUnit Test Suit Allgemeine Java-Themen 2
B Test$1.class mit dem javac compiler Allgemeine Java-Themen 7
G Input/Output System.in "umbiegen" für junit-Test Allgemeine Java-Themen 4
DEvent Test JNI Allgemeine Java-Themen 4
S Theorie hinter Shape intersects Test..? Allgemeine Java-Themen 5
fastjack jUnit und Test von equals, hashCode, toString Allgemeine Java-Themen 11
D junit - frage zu fixtures/test suites Allgemeine Java-Themen 11
G JUnit Test Allgemeine Java-Themen 5
K Test-Code in Java-Klassen verstecken (wie mit Precompiler möglich) Allgemeine Java-Themen 10
J GUI Test Allgemeine Java-Themen 4
G Implementierung vom AKS-Test Allgemeine Java-Themen 11
N ClassNotFound Exception bei JUnit Test? Allgemeine Java-Themen 2
GilbertGrape Warum schlägt JUnit-Test fehl? Allgemeine Java-Themen 19
K Bekomme JUnit TEst nicht zum laufen :( Allgemeine Java-Themen 9
G Ant: <test/> Allgemeine Java-Themen 2
F Kasiski-Test in BlueJ Allgemeine Java-Themen 4
H Java Multiplicoice Test (Part 2) Allgemeine Java-Themen 5
H Java Multiplicoice Test (10 Fragen) Allgemeine Java-Themen 11
F Test für Localization Allgemeine Java-Themen 6
B JUnit - Gleichen Test x-mal durchlaufen Allgemeine Java-Themen 2
H References to generic type Test.A<typ> should be param Allgemeine Java-Themen 5
N Performance-Test (Geschwindigkeit von Methoden vergleichen)? Allgemeine Java-Themen 4
S Performance Test mit JMeter Allgemeine Java-Themen 2
B httpunit test Allgemeine Java-Themen 6
S HTTPUnit Test Fehler: Error on HTTP request: 500 Internal Er Allgemeine Java-Themen 9
M Test eines Programmes Allgemeine Java-Themen 4
B Primzahlen test Allgemeine Java-Themen 3

Ähnliche Java Themen

Neue Themen


Oben