Testen von Java-EE-Anwendungen mit Matthias Bünger – Anwendungsentwickler-Podcast #128

Wie steigt man in das automatisierte Testen einer Java-EE-Anwendung ein, wenn man bereits eine bestehende Anwendung hat und bislang nicht getestet hat? Diese und weitere Fragen kläre ich im Interview mit Matthias Bünger in der einhundertachtundzwanzigsten Episode des Anwendungsentwickler-Podcasts.

TL;DR

Bei bestehenden Java-EE-Anwendungen starte ich mit schnellen Unit-Tests für die Fachlogik und ergänze schrittweise Tests für die Infrastruktur. Über Konstruktor-Injection kannst du Abhängigkeiten direkt übergeben und Klassen im Java-SE-Kontext testen. Echte Implementierungen kommen infrage, wenn sie schnell und zuverlässig laufen; Zugriffe auf externe Ressourcen ersetze ich zunächst durch Test doubles. Arquillian verwende ich für wenige umfassende Tests im Application-Server, die auch das Zusammenspiel mit der echten Datenbank prüfen.

Kapitelmarken

  • [00:00:01] Einstieg ins Testen von Java-EE-Anwendungen
  • [00:02:34] Matthias Bünger und sein Arbeitsumfeld
  • [00:05:09] Aufbau der Backend-Anwendung und XML-Verarbeitung
  • [00:07:57] Vorhandene Tests und Fragen zu Arquillian und Mocking
  • [00:10:50] Von der Fachlogik nach außen testen
  • [00:13:39] Automatische Regressionstests und reproduzierbare Testdaten
  • [00:15:59] Aufwand und Einsatz von Arquillian
  • [00:18:05] Domäne isolieren und Komponenten verbinden
  • [00:19:39] Persistenz mit lokalen und echten Datenbanken testen
  • [00:21:11] Testpyramide und vollständige Benutzerabläufe
  • [00:22:28] CDI und Logging im bestehenden Projekt
  • [00:24:12] Abhängigkeiten durch Konstruktor-Injection sichtbar machen
  • [00:27:09] Logger übergeben und bestehende Klassen testbar machen
  • [00:29:48] Objekte und Abhängigkeiten im Test vorbereiten
  • [00:32:10] Lesbare Tests mit sprechenden Hilfsmethoden
  • [00:33:59] Welche Abhängigkeiten werden gemockt?
  • [00:38:43] Schnelle Tests und Infrastrukturtests getrennt halten
  • [00:40:16] Den Einstieg auf Fachlogik und kurze Laufzeiten ausrichten
  • [00:42:48] Oracle oder lokale Datenbank als Testziel
  • [00:45:01] Datenbankrechte und getrennte Testkonfigurationen
  • [00:46:12] JPA im Java-SE-Kontext mit eigenem EntityManager
  • [00:49:10] Datenbanktests mit Arquillian abwägen
  • [00:51:34] Umfangreiche Mock-Setups als Anlass zum Refactoring
  • [00:54:17] Austauschbare Abhängigkeiten früh einplanen
  • [00:56:16] Quellen zum Testen und Unterschiede zwischen Stubs und Mocks
  • [00:58:54] Mockito als Framework für den Einstieg
  • [01:00:36] Clean Code und Continuous Integration
  • [01:02:21] Maven und plattformunabhängige Builds
  • [01:04:07] Kontakt und Fragen zur Episode
  • [01:05:14] Praktische Ausbildung und Hürden beim Einstieg
  • [01:07:16] Weitere Fragen und Shownotes

Probeabo bei Audible (Affiliate)

Inhalt

Allgemeines zur Person

  • Wie ist dein Name und wo arbeitest du?
    • Matthias Bünger, aus Bonn, beschäftigt beim ITZBund (Informationstechnikzentrum Bund, IT-Dienstleister).
  • An welchen Projekten arbeitest du zur Zeit in deinem Tagesjob?
    • Qualitätssicherung, Buildmanagement, automatisches Testen.
    • Automatisierung ist mir sehr wichtig. Ich möchte die Grundlagen für automatische Tests schaffen.
    • Ansonsten bin ich hauptsächlich in der Backend-Anwendung tätig.
  • Welche Ausbildung bzw. welches Studium hast du im Bereich der Informatik absolviert?
    • Nach der Schule habe ich eine Ausbildung zum Fachinformatiker Anwendungsentwicklung absolviert.
    • Danach habe ich noch Informatik studiert.
  • Mit welcher/n Programmiersprache/n arbeitest du im Alltag?
    • Java (EE)
  • Was ist deine Lieblingsprogrammiersprache und warum?
    • Java

Automatisiertes Testen von Java-EE-Anwendungen

Mein aktueller Wissensstand zum Testen ist etwas durcheinander. Ich bin verwirrt durch zahlreiche Blog-Beiträge, die unterschiedliche Meinungen propagieren. Zum Beispiel: „Mocke nur, was du unter Kontrolle hast!“ oder „Mocks sind gemacht worden, um sie wieder abzuschaffen!“. Ja was denn nun?

  • Gibt es aktuell noch gar keine Tests in eurer Anwendung?
    • Es gibt ein paar Unit-Tests ohne Mocking oder Dependency Injection.
    • In vielen Komponenten werden Logger eingesetzt, die die Tests erschweren.
    • Ich habe eine Schulung zu Arquillian besucht und kann theoretisch damit loslegen.
    • Was mich abschreckt ist das Deployment bei Arquillian, das recht lange dauert.
  • Was macht die Anwendung überhaupt? Welche Frameworks/Technologien werden eingesetzt?
    • Backend zur Verarbeitung von XML-Dateien, die ins Dateisystem geliefert werden.
    • Die Daten aus den XML-Dateien werden dann mit JPA in eine Datenbank geschrieben, von wo aus sie weiter verarbeitet werden.
    • Fachlich geht es um Freistellungsaufträge von Banken.
    • Unsere Herausforderungen sind die parallele Verarbeitung und eine hohe Last. Im Hintergrund läuft WebSphere.
    • Die fachliche Logik ist nicht allzu komplex.
  • Was sind deine Herausforderungen beim Testen?
    • Wir verwenden häufig einen Logging Interceptor. Wie mockt man den?
    • Wir setzen stark auf CDI mit @Inject an den Attributen. Wie testet man das?
    • Ansonsten gibt es viele Data Access Objects.
    • DB-Zustände müssen evtl. zum Testen hergestellt und danach zurückgesetzt werden.
  • Wie findet man einen Einstieg ins Testen?
    • Ich würde mit Unit-Tests für die Fachlichkeit beginnen. Dieser Teil der Anwendung „verdient das Geld“.
    • Die EE-Technik geht eher nicht kaputt und muss nicht zu Beginn getestet werden. Das bringt kaum Mehrwert.
    • Ich würde nicht mit Arquillian beginnen, sondern mit „einfachen“ Unit-Tests mit JUnit, ggfs. unterstützt durch Mocks mit Mockito.
  • Was mockst du?
    • Ich habe verschiedene Meinung gelesen: Nur mocken, was man vollständig versteht. Niemals Fremdimplementierungen mocken. Keine Legacy-Anwendungen mocken.
    • Das sehe ich anders: Ich mocke alles, was mir im Weg steht und insb. die Infrastruktur berührt (Netzwerk, Datenbank, Dateisystem).
    • Wenn die Mocks zu aufwändig werden, ist das ein Zeichen dafür, dass die zu testende Klasse verkleinert werden muss.
  • Würdest du auch die Datenbank mocken?
    • Erstmal ja, um die Tests zu beschleunigen.
    • Aber danach würde ich gegen eine lokale oder In-Memory-DB testen und am Schluss auch gegen eine „echte“ Datenbank, z.B. eine Entwicklungsdatenbank.
    • Die jeweilige Zieldatenbank (z.B. Oracle) ist halt nicht H2. Die Systeme verhalten sich unterschiedlich. Und wichtig ist, dass die Software später auf dem echten Zielsystem lauffähig ist.
    • Ich würde die echten DB-Tests aber nicht mit EE im Application Server laufen lassen, sondern komplett ohne Arquillian mit einem JPA-Provider wie EclipseLink oder Hibernate im SE-Kontext. Das ist schneller als ein komplettes Deployment.
  • Welche DB-Benutzer verwendest du zum Testen?
    • Technische User mit erweiterten Rechten zum Anlegen von Schemas, z.B. bei DB-Migrations nötig.
    • Ich setze auf zwei verschiedene Persistence-Units für main und test, damit der Produktivcode keine Ahnung von der zweiten DB haben muss.
  • Welche Ressourcen kannst du zum Thema empfehlen?
    • „Test automation without a headache: Five key patterns“ von Gojko Adzic auf der „Norwegian Developers Conference 2016“ in London
    • Martin Fowler – Mocks Aren’t Stubs: Hier werden die Begriffe Stub, Mock, Spike usw. erklärt und abgegrenzt, da sie häufig falsch benutzt werden.
  • Hast du eine allgemeine Buchempfehlung?
    • Clean Code* finde ich sehr wichtig, auch wenn ich nicht alle Inhalte teile. Ich habe daraufhin CheckStyle usw. eingeführt und achte mehr auf Code-Qualität und Wartbarkeit.
    • Alles rund um Continuous Integration! Automatisierung ist viel wert! Einmal aufsetzen, für immer die Vorteile genießen. Für mich wichtig ist die erreichte Plattformunabhängigkeit, keine Dependencies, die ich im Classpath manuell setzen muss etc. Bei uns kann mit Git und Maven jeder direkt in neue Projekte einsteigen. Außerdem findet der CI-Prozess auch Fehler in den Projekten.

Abschluss

  • Wo können die Hörer mehr über dich erfahren bzw. dich kontaktieren?
    • Ich bin nicht online vertreten. Facebook halte ich privat. Höchstens bei StackOverflow oder bei einer Bewerbung auf unsere Stellenausschreibungen! 😉

Literaturempfehlungen

Robert C. Martin - Clean Code: A Handbook of Agile Software Craftsmanship (Affiliate)*

Links

Zusammenfassung

Ausgangspunkt: Eine bestehende Java-EE-Anwendung testen

Im Gespräch mit Matthias Bünger gebe ich dir Einblicke aus meinen Projekten. Matthias arbeitet beim ITZ Bund an einer Backend-Anwendung, die XML-Dateien mit Meldungen zu Freistellungsaufträgen einliest und über JPA in einer relationalen Datenbank verarbeitet. Durch hohe Last und parallele Abläufe entstehen besondere Herausforderungen. Die vorhandenen Unit-Tests prüfen vor allem Hilfsfunktionen für Strings; die fachlichen Regeln sollen zusätzlich automatisch getestet werden.

Mit automatischen Tests kannst du nach Änderungen auch bereits vorhandene Funktionen erneut prüfen. Das hilft etwa bei einem Hotfix. Für reproduzierbare Ergebnisse brauchst du definierte Testdaten und einen Ausgangszustand, den du vor jedem Test wiederherstellst.

Mit der Fachlogik beginnen

Für den Einstieg arbeite ich mich von der fachlichen Domäne nach außen vor. Eine Berechnung lässt sich mit einem selbst erzeugten Java-Objekt testen, dessen Eigenschaften du passend zum Testfall setzt. Die Domäne sollte möglichst frei von technischen Abhängigkeiten sein, damit solche Tests direkt im Java-SE-Kontext laufen.

Anschließend verbinde ich Komponenten miteinander und prüfe ihre Zusammenarbeit. Sobald eine Komponente auf Infrastruktur zugreift, ersetze ich diese Abhängigkeit zunächst durch ein Test double. Ein Repository kann beispielsweise vorgegebene Datensätze liefern.

Bei einer neuen Anforderung habe ich auch schon mit einem umfassenden Integrationstest begonnen, wie es im Buch Growing Object-Oriented Software, Guided by Tests beschrieben wird. Dieser Test bleibt zunächst rot, während kleinere Unit-Tests die einzelnen Schritte begleiten. Sobald der große Test erfolgreich durchläuft, ist der gesamte Ablauf abgedeckt.

Abhängigkeiten über den Konstruktor übergeben

Wenn @Inject direkt an Feldern steht, erkennst du die benötigten Abhängigkeiten erst beim Blick in die Klasse. Ich bevorzuge inzwischen Konstruktor-Injection: Der Konstruktor bekommt die erforderlichen Objekte als Parameter und erhält die @Inject-Annotation. Im Test erzeugst du die Klasse mit new und übergibst passende Objekte selbst. Fehlende Parameter fallen dabei schon beim Kompilieren auf.

Für bestehende Klassen gibt es einen schrittweisen Weg:

  • Ergänze in der zu testenden Klasse einen package-private Konstruktor, der die bisherigen Abhängigkeiten entgegennimmt und die Felder setzt.
  • Liegt dein Test im gleichen Package, kann er diesen Konstruktor aufrufen. Der EE-Container verwendet weiterhin den vorhandenen Default-Konstruktor und füllt anschließend die annotierten Felder.

Eine Hilfsmethode im Test kann ebenfalls ein Objekt erzeugen und zugängliche Felder setzen. Dabei müssen die Abhängigkeiten bereitstehen, auf die der jeweilige Testfall zugreift.

Einen Logger übergebe ich ebenfalls über den Konstruktor. Im Test reicht beispielsweise ein Konsolenlogger oder eine Implementierung, die Ausgaben verwirft. Bei Matthias erschweren ein eigener Logging-Interceptor und CDI den bisherigen Einstieg.

Wann ich Abhängigkeiten ersetze

Echte Implementierungen bevorzuge ich, wenn sie sich schnell und zuverlässig im Test ausführen lassen. Ihr Code wird dadurch mitgeprüft. Aufwendige Ketten aus Test doubles erhöhen den Aufwand, den Test vorzubereiten.

Als Orientierung dienen mir die Grenzen zur Infrastruktur. Einen Datenbankzugriff ersetze ich zunächst, ebenso Zugriffe über das Netzwerk oder auf Dateien. Solche Abhängigkeiten können Tests verlangsamen und durch äußere Umstände fehlschlagen lassen.

Mit einem Test double lässt sich etwa ein Timeout gezielt auslösen, um die erwartete Fehlerbehandlung zu prüfen. Bei einem Datei-Downloader ergänze ich später einen Test mit einem echten Download, damit auch dieser Teil des Ablaufs geprüft wird.

Du brauchst ein klares Verständnis der ersetzten Schnittstelle und ihres Verhaltens, um passende Rückgabewerte festzulegen. Meine Entscheidung hängt davon ab, welche Funktion ich prüfen möchte und welche externen Abhängigkeiten dabei entstehen.

Datenbanktests passend zum Projekt aufbauen

Eine lokale Datenbank wie Apache Derby kann helfen, JPA-Mappings und das Speichern zusammengehöriger Entities separat zu prüfen. Dafür baust du das benötigte Schema auf und füllst es mit Testdaten.

Bei Besonderheiten einer Oracle-Datenbank muss dieser Zwischenschritt zum Projekt passen. Datentypen oder Sequences können dafür sprechen, die Persistenz direkt gegen eine Oracle-Entwicklungsdatenbank zu testen. Ein abschließender Test gegen die echte Datenbankumgebung gehört für mich dazu.

Auch solche Tests führe ich im Java-SE-Kontext aus. Mit EclipseLink oder Hibernate erzeuge ich einen eigenen EntityManager, den ich den zu testenden Objekten übergebe. Eine eigene persistence.xml im Testbereich legt die Verbindung zur Entwicklungsdatenbank fest. Der Produktivcode erhält seine Abhängigkeiten von außen.

Beim Vorbereiten und Aufräumen können zusätzliche Datenbankrechte erforderlich sein. Im Gespräch kommt deshalb auch die Möglichkeit zur Sprache, mit Arquillian unterschiedliche Datenquellen für diese Aufgaben und für die Geschäftslogik zu verwenden. Die Testkonfiguration muss sicher auf die vorgesehene Testumgebung zeigen, damit Tests von der Produktionsdatenbank getrennt bleiben.

Arquillian und die Testpyramide

Mit Arquillian teste ich die Anwendung im echten Application-Server. Dabei lässt sich prüfen, ob die Komponenten einschließlich der EE-Funktionen zusammenspielen. Das Deployment kostet Zeit; zusätzlich muss das Testarchiv alle erforderlichen Abhängigkeiten enthalten. Fehlerhafte Deployments haben in meinen Projekten auch manuelle Neustarts erforderlich gemacht.

Meine Tests folgen der Testpyramide. Viele schnelle Unit-Tests decken die Fachlogik ab. Ergänzend kommen kleinere Integrationstests hinzu. Für vollständige Abläufe im Application-Server verwende ich wenige umfassende Tests, etwa eine Benutzerinteraktion, bei der eine Entität angelegt und anschließend verändert oder gelöscht wird.

Tests mit Infrastrukturzugriff lege ich getrennt von schnellen Tests ab, beispielsweise in einem eigenen Source-Ordner. So kannst du gezielt die Tests ausführen, die innerhalb weniger Millisekunden Rückmeldung geben. Kurze Laufzeiten helfen mir, während der Arbeit bei der Aufgabe zu bleiben.

Testcode verständlich halten

Für wiederkehrende Voraussetzungen schreibe ich kleine Hilfsmethoden mit sprechenden Namen. Eine Methode wie "angenommen, Session kann erzeugt werden" kapselt das erforderliche Setup und macht den eigentlichen Test leichter lesbar.

Wenn ich umfangreiche Vorbereitungen und viele Test doubles benötige, prüfe ich die Größe der Klasse und ihre Abhängigkeiten. Das Aufteilen einer Klasse kann die Tests vereinfachen. Auch Testcode muss verständlich bleiben, damit du ihn später anpassen kannst.

Begriffe und Quellen

Im Gespräch verwende ich häufig "Mock" als Sammelbegriff. Fachlich lohnt es sich, genauer hinzusehen:

  • Stubs liefern vorgegebene Werte und reichen häufig aus, um benötigte Abhängigkeiten bereitzustellen.
  • Mocks zeichnen Interaktionen auf, mit denen sich beispielsweise Methodenaufrufe prüfen lassen.

Für den Einstieg nennt Matthias Mockito, weil dazu viele Tutorials und Dokumentationen verfügbar sind. Die Methode zum Erzeugen eines solchen Objekts heißt dort mock, auch wenn das Objekt im Test als Stub eingesetzt wird.

Als weitere Quellen werden der Vortrag Test Automation Without a Headache: Five Key Patterns von Gojko Adzic und ein Artikel von Martin Fowler über unterschiedliche Test doubles genannt. Matthias empfiehlt außerdem Clean Code, wobei er einen Großteil der Aussagen teilt.

Tests in automatisierte Builds einbinden

In meinen Projekten gehören automatische Tests zur Build-Pipeline. Continuous Integration macht Abläufe wiederholbar und deckt Probleme auf, die auf dem eigenen Rechner verborgen bleiben, etwa eine fehlende Datei.

Matthias beschreibt, wie Maven das Einrichten seiner Projekte vereinfacht hat: Abhängigkeiten werden über das Build-Tool bereitgestellt, sodass Entwickler:innen das Projekt aus Git holen und in Eclipse importieren können. Für Tests müssen außerdem externe Verbindungen austauschbar sein, etwa die URL eines REST-Dienstes. Solche Möglichkeiten lassen sich früh beim Entwickeln einplanen.

Transkription der gesamten Episode

Automatisch erzeugte Transkription der Episode

[0:01] Herzlich Willkommen zum Anwendungsentwickler-Podcast, dem Podcast rund um die Ausbildung zum Fachinformatiker für Anwendungsentwicklung.

[0:10] In dieser Episode geht es um den Einstieg ins Testen von Java IE-Anwendungen. Viel Spaß!

[0:20] Hallo und herzlich Willkommen zur 128. Episode des Anwendungsentwickler-Podcasts.

[0:27] Mein Name ist Stefan Macke und heute haben wir ja, wenn ich das Ding in binär umrechnen würde, die 10.000.000. Episode.

[0:34] Der Hammer. Ist ja noch viel cooler als die 100. Episode im Dezimalsystem, oder?

[0:39] Ja, wie schön, dass wir alle die Dualzahlen beherrschen. Da kann man sich mal richtig freuen, dass man so eine tolle Episode aufgenommen hat.

[0:45] Jetzt kommen wir aber zurück zum Thema und zwar habe ich heute ein Interview und zwar ein ganz besonderes Interview.

[0:50] Und zwar bin ich heute eigentlich der, der interviewt wird, denn ein Podcast-Hörer, will ich jetzt nicht sagen, aber jemand, der mich auf der Java-Land dieses Jahr gesehen hat,

[0:58] mit meinem Vortrag zum Thema Testen von Java IE-Anwendungen, hat mir eine Mail geschickt und gefragt, ob wir uns mal unterhalten können,

[1:05] weil er ja einen Einstieg sucht in das Thema Testen von Java IE-Anwendungen oder ganz allgemein von Enterprise-Anwendungen.

[1:13] Und zwar Matthias Bünger. Mit dem spreche ich heute genau über dieses Thema.

[1:18] Wie kann man denn vielleicht in das Testen einer bereits bestehenden Enterprise-Applikation einsteigen?

[1:24] Wo liegt man los? In der Domäne, an den Rändern, bei der Technik, mit Unit Tests, mit Integrationstests und so weiter und so fort.

[1:30] Und dazu bin ich heute mal der, der so ein bisschen Rede und Antwort steht, denn ich habe das Ganze jetzt in ein paar Projekten auf der Arbeit auf jeden Fall intensiv betrieben.

[1:38] Und ja, ich erzähle einfach mal, was so meine Ideen dazu sind. Soll man mocken? Wenn ja, was? Was wird vielleicht gar nicht gemockt? Hin und her.

[1:46] Das sind alles Themen, über die wir heute sprechen wollen. Du brauchst ein bisschen Verständnis von Java IE, sonst wirst du sicherlich einige Sachen nicht so richtig verstehen,

[1:53] weil es sind doch einige Fachbegriffe dabei, die man außerhalb vom IE-Umfeld vielleicht dann doch nicht so ganz versteht.

[1:59] Deswegen, wenn du in dem Umfeld zu Hause bist, dann ist das heute genau das Richtige für dich.

[2:03] Ansonsten höre trotzdem gerne rein, aber wundere dich nicht, wenn wir zwischendurch über Equillion und Interceptors und Inject und verschiedene andere Dinge sprechen,

[2:12] die dann doch etwas spezifisch für den Java-Kontext sind.

[2:17] Aber auch ganz allgemein wirst du heute, glaube ich, ein bisschen was zum Thema Testen mitnehmen.

[2:21] Von daher höre ich jetzt auch mal auf mit dem vorgeplänkel und leite direkt über zum Interview, das Matthias mit mir geführt hat. Viel Spaß!

[2:34] Ja, hallo Matthias! Schön, dass das heute geklappt hat zu unserem kleinen Interview.

[2:39] Ich bin mal gespannt, wie wir in den nächsten paar Minuten uns dem Thema Testen vielleicht nähern.

[2:44] Aber bevor wir da einsteigen, erzähl doch mal vielleicht ganz kurz in ein paar Sätzen, was zu dir.

[2:48] Wer bist du? Was machst du so? Wo arbeitest du? Ja, leg doch mal los!

[2:52] Ja, hallo! Also ich bin Matthias. Ich bin Softwareentwicklung im öffentlichen Dienst beim ITZ Bund.

[2:59] Das ist der IT-Dienstleister des Bundes. Ich habe meine Ausbildung zum Fachinformatiker für Anwendungsentwicklung nach der Schule gemacht.

[3:09] Anschließend in dem Bereich gearbeitet und parallel zur Arbeit studiert, Informatikstudium.

[3:15] Und bin jetzt seit mehreren Jahren Vollzeit als Softwareentwicklung tätig.

[3:22] Wir entwickeln Java-Enterprise-Anwendungen. Das ist auch die Sprache, mit der ich primär zu tun habe.

[3:30] Klar, in der Ausbildung und so hat man immer noch ein bisschen was anderes.

[3:33] Aber ich habe Java jetzt auch für mich als Lieblingssprache identifiziert.

[3:39] Und wir benutzen im Java-Enterprise-Umfeld halt ganz viel Automatismus, weil unsere Anwendung primär eine Backend-Anwendung ist.

[3:50] Und da ich zeitweise auch weniger entwickelt habe, als viel mehr QS gemacht habe und immer schon mein zweites Steckenpferd,

[4:03] so Bildmanagement, automatisches Testen und sonst irgendwas in die Richtung gemacht habe,

[4:08] weil ich einfach diesen Automatismus-Faktor für sehr wichtig halte, versuche ich seit einiger Zeit neben meinen Haupttätigkeiten,

[4:19] wenn ich mal irgendwie Lücken habe, die Grundlagen zu schaffen, dass wir automatisch testen, unsere Enterprise-Anwendung.

[4:27] Und bin in dem Zusammenhang dann auf die Probleme beim Wann-teste-ich-was, beziehungsweise genauer formuliert Wann-mocke-ich-was,

[4:39] ja, auf diverse Konferenzartikel, unter anderem halt den von dir, von der Java Land diesjahr, gestoßen.

[4:49] Und umso mehr ich gelesen habe, umso mehr ich Konferenzbeiträge mir angeguckt habe, umso verwirrter war ich.

[4:57] Und dann dachte ich mir, ich brauche mal irgendwen, der da Erfahrung hat, um mich einfach mal mit dem aktiv auszutauschen.

[5:05] Warum? Was? Was vielleicht nicht? Und so weiter.

[5:09] Da würde ich jetzt gerne nochmal einmal einsteigen. Also du machst quasi Full-Stack-Java, sagt man das so.

[5:16] Machst du auch irgendwas im Frontend oder wirklich nur im Backend? Das hattest du jetzt gerade gesagt.

[5:20] Also das, wo ich primär einsteigen will, oder die Hauptteile sind Backend-Verfahren.

[5:28] Wir haben auch eine kleine Web-Oberfläche, die also fast im Prinzip nur für Administration und Konfiguration der Anwendung ist.

[5:37] Also der Hauptfokus der Anwendung liegt schon im Backend-Bereich.

[5:44] Und das kann man sich wie vorstellen? Das ist so eine ganz klassische Java-EE-Anwendung mit einer REST-Schnittstelle,

[5:51] oder sind das irgendwelche SOAP-Services oder JSF-Web-Oberfläche? Wie kann man sich das ganz grob vorstellen, was da im Backend läuft?

[5:57] Grob vorstellen kann man das so, dass wir einen Nachrichteneingang über XML haben,

[6:03] wobei die Schnittstellen nach außen dann nochmal unterschiedlich sind, aber im Prinzip kriegen wir XML-Nachrichten,

[6:08] teilen die in dem ersten Schritt auf auf Datenbank-Tabellen, dass wir sie dann entsprechend mit Java-Bordmitteln schön verarbeiten können

[6:19] und verarbeiten dann inhaltlich diese Sachen.

[6:23] Also es geht um Freistellungsaufträge und da müssen die Banken melden an das Bundeszentralamt für Steuern

[6:30] und diese Meldungen werden halt verarbeitet. Das ist dann hochparallel und auch mit dem,

[6:37] also wir versenden WebSphere mit WebSphere Processor auch und im Grunde lässt es sich aber alles auf Java Enterprise runterbrechen.

[6:48] Sprich keine Web-Services so für die Verarbeitung, die in unserer Hand liegt,

[6:55] sondern halt JPA-Prozesse, also JPA ist viel involviert, weil wir halt die Datenbank ständig brauchen

[7:05] und ansonsten normale Verarbeitungslosigkeit. Also das ist nicht unbedingt komplex in der Verarbeitung.

[7:13] Die Komplexität ist primär die Parallelität und die Last, was aber natürlich nicht davon entbindet,

[7:21] dass wir auch fachliche Logik natürlich drin haben, die getestet werden möchte.

[7:27] Und du sagst jetzt, dass das XML kommt da rein. Sind das tatsächlich XML-Dateien, die da irgendwo in einem Verzeichnis liegen

[7:33] oder werden die wirklich über so einen, keine Ahnung, Soap-Service da eingespielt oder wie ist da die Schnittstelle?

[7:38] Wie kommt das XML da rein?

[7:40] Wir kriegen XML-Nachrichten in Dateiform und dann lesen wir die ein, verarbeiten die und also zerlegen die, verarbeiten die.

[7:46] Gut. So und dann kommt das Zeug quasi im Backend an, wird irgendwie erstmal auseinandergenommen

[7:51] und in irgendwelche Datenbank-Tabellen gepackt in eine relationale Datenbank, nehme ich an, dann mit JPA oder?

[7:56] Genau.

[7:57] Gut. Okay. Und wie ist aktuell der Stand der Tests? Also gibt es überhaupt irgendwas, was getestet wird

[8:04] oder gibt es da noch gar keine automatischen Tests in irgendeiner Form?

[8:06] Also automatische Tests gibt, es gibt eine Handvoll Unit-Tests, die wir halt für klassische Unit, also für klassische Unit-Testfähige Funktionen,

[8:18] sag ich mal, also ohne irgendwie Dependency Injection oder sonst irgendwas, verwenden.

[8:22] Das sind aber, kann man sich vorstellen, relativ wenig, weil wir überall mindestens mal einen Logger drin haben.

[8:30] Und dementsprechend, also ich hatte letztes Jahr schon eine Schulung zu Equillien, weil ich mir gesagt habe,

[8:38] okay, Java Enterprise Testen liest man ständig Equillien, das, was man so darüber liest, klingt auch sinnvoll.

[8:45] Die Schulung war auch richtig gut, sodass ich theoretisch anfangen könnte.

[8:51] Jetzt ist es aber halt so, dass bei einem Equillien-Testen immer ein Deployment stattfindet gegen einen Application-Server und das halt auch immer entsprechend Zeit kostet.

[9:00] So. Das ist ja dann, aber Aussage in diesem, in dieser Schulung war zum Beispiel, Mocks sind dafür gemacht worden, um sie wieder abzuschaffen.

[9:11] Dann habe ich dieses Jahr deinen Vortrag auf der Java Land gehört, wo du ja das ganze Testen mehr so ein bisschen in Richtung, unter dem Aspekt der Zeit betrachtet hast,

[9:24] wo du sagst, viel mit Mocks, um schnell viel zu testen und am Ende halt so ein paar, im Verhältnis, ein paar Equillien-Tests, um die Integration sicherzustellen.

[9:38] Ist ja im Prinzip ein völlig anderer Ansatz, aber auch halt unter einem, ja, ein völlig anderer Ansatz unter einem völlig anderen Aspekt.

[9:46] Dann liest man noch, oder Konferenzbeiträge, wo gesagt wird, ja, mocke nur das, was du unter Kontrolle hast, alles andere nicht.

[9:58] Was wieder ein anderer Ansatz ist und umso mehr ich mich halt damit beschäftigt habe, umso mehr dachte ich mir so, ja, wie denn jetzt?

[10:09] Dann die Probleme, die ich einfach mangels Zeit und weil ich es halt nur nebenbei mache, habe, dass ich mit dem Mocken noch nicht so technisch klarkomme, liegen wahrscheinlich ein bisschen an der mangelnden Erfahrung.

[10:26] Vielleicht aber auch daran, dass die meisten Tutorials, ja, so klassische Hello-World-Tutorials, sag ich mal, sind und wir mit Dependency Injection und Logging Interceptor halt Java Enterprise benutzen.

[10:44] Und zu den Sachen, wie mocke ich denn sowas, findet man dann auch schnell mal nichts.

[10:50] Ja, das kann ich verstehen, dass das verwirrend ist. Das ist auch bestimmt so. Ich hatte das beim Einstieg auch, dass ich mir erstmal alles mögliche angeguckt habe und festgestellt habe, ich brauche irgendwie meinen eigenen Weg und gucke, was für mich funktioniert.

[11:02] Und ich würde tatsächlich dazu vertreten, wie ich es auch im Vortrag gesagt habe, ich mocke mir erstmal alles raus, damit ich einfach wirklich rattenschnell die Tests durchführen kann.

[11:12] Ich habe heute noch an einer anderen Enterprise-Applikation gearbeitet und wie du schon sagtest, Aquilin-Tests sind super gut. Die werden in ein echtes Ziel deployed und laufen da auch ab, quasi wie in echt, nur die sind halt einfach saulangsam.

[11:27] Und wenn dir da mittendrin dann einer abratzt, dann wartet, oder ich habe ganz oft zum Beispiel auch das Problem, wenn so ein Aquilin-Test abraucht aus irgendeinem Grund, was weiß ich, da gibt es dann mal irgendwo einen Null-Pointer, weil ich irgendwas vergessen habe, dann bleiben teilweise auch die Deployments in einem Ziel-Server hängen.

[11:40] Mache ich das drei, vier Mal, ratzt mir der komplette, bei uns ist es ein JBoss zum Beispiel, als Ziel-Server ab, weil er so viele kaputte Deployments hat, dann muss ich den manuell durchstarten und hin und her.

[11:50] In der Praxis, das hört sich erstmal alles ganz cool an, aber gerade wenn man es entwickelt und die Tests selber vielleicht auch noch den einen oder anderen Fehler enthalten, weil man halt in der Entwicklung ist, ist das schon sehr langsam und auch einfach super nervig, wenn man auch noch mit der Infrastruktur rumfrickeln muss.

[12:05] Also, ich persönlich fange damit überhaupt nicht an, sondern ich mache erstmal wirklich von innen nach außen meine Domain-Logik, komplett Unit-Tests und wenn dann irgendwie Dependencies dazukommen, rausmocken, die Frameworks, die du auch schon gesagt hast, JPA zum Beispiel, erstmal rausmocken, dann vielleicht noch eine kleine Datenbank dazu nehmen, eine Memory-Datenbank, gegen die mal testen und ganz am Ende mache ich dann einen Integrations-Test,

[12:26] beziehungsweise andersherum auch, wenn ich sicherstellen muss, dass eine komplette Integrations-Logik auch funktioniert, fange ich durchaus auch mal mit einem Integrations-Test an, so ein bisschen wie in dem Buch beschrieben, Growing Object-Oriented Software Guided by Tests, die fangen mit einem einzigen Integrations-Test an, der richtig groß ist, von vorn bis hinten alles abdeckt, aber nur ein einziger Test und dann wird der quasi, bleibt ganz lange rot und wird irgendwann Schritt für Schritt grün, indem man andere kleine Unit-Tests ergänzt und das habe ich auch schon ein paar mal gemacht, wenn ich wirklich, sage ich mal, eine Anforderung zu lösen hatte,

[12:56] die ich so zum Beispiel noch nicht umgesetzt habe oder ich war mir noch nicht sicher, wie ich es genau machen soll, dann habe ich halt irgendwie immer so einen, wie soll man sagen, einen großen Test drüber schweben und wenn der dann irgendwann grün ist, weiß ich, dass ich fertig bin, aber ansonsten würde ich grundsätzlich eigentlich immer von innen nach außen arbeiten und diese ganzen Schnittstellen zum Beispiel und auch insbesondere dieses ganze Java-EE-Zeug erstmal völlig ignorieren, sondern mich wirklich erstmal nur auf die Domäne konzentrieren und da hattest du jetzt gesagt, ihr habt schon einige Unit-Tests, auch ohne Box und Dependency Injection und so weiter, aber was testen die denn?

[13:24] Also testen die tatsächlich eure Fachlogik? Du hattest jetzt zum Beispiel gesagt, es geht da irgendwie um Freistellungsaufträge, also wird da wirklich irgendwie eine Berechnung oder irgendwas getestet oder, also haben die einen fachlichen Hintergrund, die Tests oder sind die schon eher Framework- oder Technik-spezifisch?

[13:39] Ne, also die Tests, die wir haben, sind im Prinzip so String-Util-Tests, also die irgendwas, irgendwelche Formatierungssachen, die wir während der Verarbeitung machen, sicherstellen, dass wir uns da nicht irgendwie, keine Ahnung, Night-Pointer-Exception oder sonst irgendwas durch die Formatierung reinziehen, aber sie prüfen halt im Moment noch keine fachliche Logik

[14:01] und deswegen möchte ich halt auch anfangen, um die fachliche Logik automatisiert zu testen, weil manuelle Tests, ja, kann ich machen, brauchen aber halt immer entsprechend viele Ressourcen, also vor allen Dingen humane Ressourcen und Zeitressourcen

[14:21] und ja, auch teilweise ist es dann ja auch immer schwieriger, einen geeigneten Testdatenbestand oder eine Testsituation vorzugeben und bei automatischen Tests muss ich mich ja sowieso Gedanken darüber machen, Lösungen zu finden, jedes Mal sauber den Ausgangszustand wiederherzustellen.

[14:45] Das mache ich im Prinzip halt dann nur einmal die Gedanken und nicht jedes Mal neu und ich habe bei den automatischen Tests halt auch, selbst wenn ich nur eine Sache ändere, weil, keine Ahnung, Hotfix oder so, kann ich mit den automatischen Tests halt sofort einen kompletten Regressionstest machen und stelle sicher, dass ich mir nicht irgendeine andere Stelle zerschieße.

[15:05] Was ja bei manuellen Tests, gerade wenn es Hotfix schnell irgendwie gehen muss, ja okay, in dem Bereich habe ich nichts geändert, teste ich vielleicht jetzt mal nur oberflächlich.

[15:15] Deswegen sehe ich diesen Zeitaspekt, den du ja präferierst oder dem du eine sehr hohe Bedeutung zulegst, auch als sehr wichtig an, um einfach schnell viele Tests zu kriegen, die ich nicht zwingend durch eine echte Integration mit Equilien sicherstellen muss.

[15:37] Gerade wenn es halt im Prinzip nur um einfache Berechnungen geht, wo ich im Prinzip mir, ja ich sage jetzt mal vereinfacht, einen POJO oder eine Entity erstelle manuell, gewissen Eigenschaften und die in die Berechnung reinschmeiße und wo ich im Prinzip nur dadurch aufgehalten werde, dass ich halt Dependency Injection oder Interceptors habe.

[15:59] Okay, gut, dann würde ich da auch tatsächlich erstmal einsteigen. Ich glaube, da hättest du auch den größten Benefit davon. Also ich habe jetzt gerade mal eine E-Anwendung vor Augen, an der ich gerade entwickle.

[16:09] Ganz viel von dem EE-Kram ist ja sowas wie hier eine Annotation dran und da noch irgendwie eine Magic-Methode aufrufen oder hier so ein Interceptor dran und dann passiert da einfach irgendwas Magisches im Hintergrund.

[16:21] Dass das Zeug irgendwo letztlich funktioniert, weil es ja im EE-Standard ist, da gehe ich einfach mal von aus. Das heißt, ich würde mir sehr intensive Tests rund um diese Technik einfach sparen.

[16:32] Ich meine, das muss letztlich irgendwo funktionieren und dass diese Magic funktioniert, sehe ich auch wirklich nur dann, wenn ich es mal in den Application Server reindeploye.

[16:39] Also dafür finde ich Equilien super gut und auch super wichtig. Also ich sage nicht, dass man es weglassen sollte. Im Gegenteil, ich finde das sehr wichtig, ganz am Ende, wenn man alles fertig hat, das auch mal in seiner Gesamtheit zu testen.

[16:48] Das würde ich auf jeden Fall auch tun und Equilien macht es auch wirklich sehr einfach und es ist auch sehr zuverlässig, das muss man schon sagen.

[16:54] Aber ich finde es zum Beispiel an dem, was du gerade gesagt hast, ich teste hier eine kleine Berechnung, dafür würde ich niemals ein Deployment machen, weil es einfach viel zu lange dauert, viel zu fehleranfällig ist und das nervt mich einfach.

[17:05] Allein das Test-Setup ist ja riesig. Du musst ja quasi ein deploybares WAR-File oder IR-File zum Beispiel bauen lassen. Das ist ein mega Aufwand.

[17:14] Ich habe heute noch bestimmt eine halbe Stunde nur an dem Deployment gesessen, um alle Abhängigkeiten sauber mit zu deployen. Also gruselig.

[17:21] Da muss man sich wirklich teilweise die Bibliotheken, die zum Beispiel wir bauen unser Zeug mit Gradle, was wir in den ganzen Dependencies von Gradle schon drin stehen haben,

[17:29] darf ich jetzt quasi nochmal händisch in das automatisierte Bauen dieses WAR-Files stecken, was in einem Java-Code-Schnipsel laufen muss, damit Equilien ausführen kann.

[17:38] Es gibt da zwar so eine Gradle-Integration, aber die hat in diesem Fall nicht sauber funktioniert und dann ging das wirklich so los.

[17:44] Package einer bestimmten Klasse mit ins WAR-File packen, deployen lassen, gucken, ob es läuft.

[17:49] So ein Deployment dauert dann mal eben eine Minute, dann bricht er ab wegen No-Class-Dev-Found-Error.

[17:53] Also nächste Klasse dazu wieder deployen, hin und her. Das habe ich bestimmt eine halbe Stunde gemacht, bis ich alle Dependencies drin hatte und jetzt läuft es auch.

[18:00] Das ist auch ganz toll, aber der Weg dahin war enorm müßig und die Tests sind einfach immer noch grottenlangsam.

[18:05] Also ganz am Ende, ja, für eine komplette End-to-End-Geschichte am besten irgendwo das Ding komplett deployen mit allen Dependencies, irgendwo ein XML-File hinschmeißen und gucken, dass es am Ende in der Datenbank läuft.

[18:16] Super Geschichte, kompletten Integrations-Test würde ich unbedingt machen, aber anfangen würde ich damit auf keinen Fall, sondern ich würde von innen nach außen so vorgehen, dass im Inneren meine ich immer meine fachliche Domäne, die hoffentlich völlig frei von irgendwelchen EE-Annotationen oder Abhängigkeiten ist.

[18:30] Und wenn ich die mit Unitests abgedeckt habe, dann würde ich mir die Komponenten angucken, die vielleicht miteinander interagieren, also Stichwort Dependency-Injection, die Schritt für Schritt vielleicht zusammenstöpseln.

[18:40] Da muss man auch nicht unbedingt mit Mocks arbeiten, ich kann ja auch die echten Dependencies einfach reingeben, dann teste ich die automatisch mit quasi und sobald ich aber irgendwelche Komponenten habe, die mit der Infrastruktur reden, also jetzt in deinem Fall vielleicht irgendwelche Entities, die persistiert werden sollen über JPA, dann würde ich mir da an der Stelle Gedanken machen, wie ich das rausmocken kann, denn das wird sonst einfach viel zu langsam und natürlich auch fehleranfällig, weil ich eine echte Datenbank brauche oder sonstige Sachen.

[19:03] Also ich versuche immer so, die Domäne zu isolieren, dass ich gar keine technischen Abhängigkeiten habe, weder zu JPA noch zu anderen Frameworks und wenn es auch zum Beispiel das Logging da ist, das würde ich komplett versuchen zu eliminieren und wenn ich dann meine Fachleh-Logik sauber getestet habe, dann kann man mal gucken, wie man das in die Infrastruktur reinbekommt und da würde ich dann zum Beispiel, weiß ich nicht, wenn man jetzt mit JPA arbeitet und vielleicht so einen Repository-Pattern anwendet oder sowas, könnte man das Repository halt rausmocken und dann halt eben Fake-Datensätze liefern lassen.

[19:32] Die Testen sind halt immer noch super schnell, aber ich habe schon mal den nächsten Schritt in Richtung der Persistenz gemacht.

[19:39] Wenn ich dann als nächsten Schritt zum Beispiel testen will, dass es auch wirklich in der Datenbank landet, dann kann ich den Weg gehen und so eine In-Memory-Datenbank nehmen oder hier zum Beispiel Apache Derby, die man ab der Kommando-Zeile einfach starten kann, beziehungsweise direkt aus Java raus und da drin quasi die Datenbankstruktur nachbauen, die auch in der Ziel-Datenbank ist.

[19:55] Das Problem dabei ist natürlich, dass es nie die echte Datenbank ist, also keine Ahnung, wenn wir im Backend zum Beispiel, wir haben eine fette Oracle-Datenbank, da kann ich mit Apache Derby ein paar Tests machen, aber das simuliert natürlich nicht mal ansatzweise die korrekte …

[20:07] echte Umgebung, deswegen sage ich auch immer, dass der letzte Integrationstest am besten gegen eine echte Datenbank auch

[20:13] einfach, der Ding darf man nicht weglassen, das muss man trotzdem noch machen.

[20:15] Aber um wenigstens, sage ich mal, diesen Teil der Persistenz in Isolation testen zu können,

[20:21] nutze ich zum Beispiel dann ganz gerne so kleine Datenbanken, die man mit 3-Zeilen-Code quasi hochfahren kann, lokal,

[20:27] und ja, mit Testdaten füllt und guckt, ob es dann einfach funktioniert.

[20:30] Das würde ich dann schon machen, gerade wenn es Datenbanklast,

[20:33] oder wenn das Projekt Datenbanklastig ist, dann würde ich schon schauen, dass ich den Teil separat einfach teste,

[20:39] und wenn ich das mache, dann kann ich diese Datenbanklogik, die Persistenzlogik,

[20:44] was auch immer, ich habe eine große Entity, die hat irgendwelche Unterentities, und ich muss sicherstellen, dass das auch wirklich alles persistiert wird,

[20:49] das kann ich zum Beispiel ja wunderbar gegen so eine Derby-Datenbank machen,

[20:53] und wenn ich dann ganz am Ende einen kompletten Riesen-Integrationstest mit Equillion gegen eine echte Umgebung,

[20:58] gegen eine Entwicklungsdatenbank oder irgendwas laufen lassen kann,

[21:01] dann sehe ich ja spätestens dann, dass die einzelnen Komponenten auch zusammen funktionieren,

[21:05] aber ich würde zum Beispiel nie die einzelnen kleinen Funktionalitäten jedes Mal mit einem Riesen-Equillion-Test machen,

[21:11] also das ist für mich, da würde ich wirklich diese Testpyramide so ein bisschen im Auge halten,

[21:14] ganz, ganz viele Unit-Tests, weniger Integrationstests, und ganz am Ende dann wirklich einen kompletten Systemtest mit Equillion,

[21:21] aber dann wirklich auch zum Beispiel, ich mache wirklich so eine Art User-Journey durch die Anwendung,

[21:27] das heißt, ich stelle mir vor, das Ding ist einfach leer, dann legt der User vielleicht irgendwie eine Entität an,

[21:32] die wird in dem Integrationstest angelegt, danach wird sie vielleicht verändert, gelöscht, hin und her,

[21:36] also den kompletten Lebenszyklus, das kann man ja bei Equillion wunderbar machen,

[21:39] die Tests werden in einer bestimmten Reihenfolge ausgeführt, wenn man das vorgibt,

[21:42] und so kann ich eine komplette Benutzer-Interaktion damit simulieren,

[21:46] und dafür benutze ich Equillion wirklich sehr gerne, weil ich es dann in ein echtes Target,

[21:51] einen echten Application-Server deploye, und von draußen wie ein Client damit arbeite,

[21:55] und das bietet mir natürlich das Mocking oder die Unit-Tests auf gar keinen Fall,

[21:59] also da sehe ich echt den super Benefit, und dafür mache ich es auch,

[22:02] aber davon habe ich vielleicht 2, 3, 4, 5, vielleicht auch 6,

[22:05] und die 300 Unit-Tests darunter, die testen mir dann den Rest ab,

[22:09] also so gehe ich immer vor.

[22:11] Das Schöne dabei ist halt, dass ich mich auch von Anfang an nicht auf diese ganzen Technologie-Sachen fokussieren muss,

[22:17] wie kriege ich das rausgemockt, wie kriege ich das hin, dass diese Annotation auch funktioniert,

[22:21] ohne Java-EE-Kontext und diesen ganzen Kram,

[22:24] spare ich mir halt, wenn ich meine Domäne so modelliere, dass ich den ganzen EE-Kram da einfach gar nicht drin habe.

[22:28] Jetzt ist eigentlich die Frage, du hast jetzt ja ein bestehendes Projekt,

[22:32] da kannst du jetzt nicht einfach alles rausschmeißen, was da schon drin ist,

[22:34] wie sieht denn eure Domäne aus, also ist das alles wirklich stark mit den EE-Sachen verdrahtet,

[22:41] oder ist die Domäne noch frei von den ganzen Annotationen zum Beispiel?

[22:44] Ne, sie ist stark verdrahtet, primär halt über den Logging-Interceptor,

[22:49] beziehungsweise halt über CDI, und bei meinen bisherigen Versuchen bin ich halt zum Beispiel auch am Logging-Interceptor dann auf die Nase gefallen,

[22:57] also wir nehmen halt den, haben uns halt eine Logging-Annotation geschrieben,

[23:02] um einfach nur unsere Methoden mit der Annotation zu versehen,

[23:06] um nicht jedes Mal Log.Entry bla bla bla, Log.Exit bla bla bla,

[23:12] und haben in den Interceptor auch noch ein bisschen Performance-Logging eingebaut,

[23:19] halt um den Code einfach jedes Mal rauszuziehen und die eigentliche, den eigentlichen Quellcode der Methoden zu reduzieren und übersichtlicher zu machen,

[23:29] und das benutzen wir halt überall, damit wir zum Tracen, also während der Entwicklung zum Tracen, ja, überall eingreifen können,

[23:40] beziehungsweise überall sehen, wann läuft der wie und mit was,

[23:44] um einfach schnellstmöglich Fehler zu finden, und das funktioniert auch sehr gut.

[23:49] Dementsprechend haben wir mindestens das mal überall,

[23:53] ja, und CDI, dadurch, dass wir im Prinzip auch überall Datenbankkontakt haben,

[24:00] haben wir im Prinzip auch jedes Mal CDI für Entity Manager, beziehungsweise die entsprechenden Datenbankverbindungen, also DAO-Klassen, sonst irgendwas.

[24:12] Und wenn du jetzt sagst CDI, fange ich damit mal einmal an,

[24:16] das ist wahrscheinlich mit der AddInject-Annotation irgendwie, hängen die am Konstruktor oder direkt an den Attributen?

[24:23] An den Attributen.

[24:25] An den Attributen, okay.

[24:26] Da wäre dann tatsächlich meine Empfehlung, wenn man das irgendwie umstellen kann, wäre das schon sehr gut, wenn dann,

[24:32] also ich habe es am Anfang auch, ich habe es glaube ich sogar noch Anfang des Jahres auch in meinem Vortrag gezeigt, dass ich das auch so gemacht habe,

[24:37] die injects einfach direkt an die Attribute gepackt, hat den zentralen Nachteil, dass ich halt von draußen nicht sehe, wie diese dependencies aussehen.

[24:45] Das heißt, wenn ich nicht in die Klasse reingucke, sehe ich ja nirgendwo, was da eigentlich alles injected werden muss,

[24:49] mache ich einfach einen Konstruktor, der die ganzen Parameter bekommt und hänge das eine AddInject davor,

[24:54] dann habe ich sowohl die Möglichkeit im Test das Ding halt direkt zu newen und da dann die mocks reinzugeben,

[25:01] als auch im Application Server läuft das ja exakt genauso, nur dass ich halt den Vorteil habe,

[25:06] dass ich auch den Konstruktor ohne EE-Kontext nutzen kann.

[25:09] Und so mache ich es inzwischen auch.

[25:11] Vorher, also ich meine, das geht auch, wenn es direkt an den Attributen steht, ja.

[25:14] Dann mache ich die halt irgendwie package private und kann dann aus dem Test heraus da auch mocks reinhauen.

[25:18] Das ist aber ziemlich umständlich und ich finde es vor allem wichtig, dass es halt explizit ist, welche Abhängigkeiten eine Klasse hat.

[25:24] Und das ist meiner Meinung nach, ich habe jetzt nach und nach alle Projekte darauf umgestellt,

[25:28] über Konstruktor-Injection zu arbeiten und dann kann ich in den Tests einfach in der Before-Methode

[25:33] zum Beispiel meine ganzen Mocks hochfahren, wenn ich sie brauche und gebe die einfach dem Konstruktor meiner zu testenden Klasse rein.

[25:39] Und dann ist die Abhängigkeit explizit.

[25:41] Der Compiler meckert auch, wenn irgendwas fehlt, ja, kann mir helfen, was ich noch brauche und so weiter.

[25:45] Das hat also, denke ich, einen großen Vorteil und dadurch wird das wenigstens schon mal deutlich sichtbar,

[25:51] was ich da an Abhängigkeiten habe und reingeben muss.

[25:54] Zweite Frage ist dann natürlich, ob ich das alles mocken muss oder ob ich nicht auch einfach die echten Implementierungen reingeben kann.

[25:59] Ich würde natürlich immer die echten bevorzugen.

[26:01] Mocks muss ich natürlich auch wieder, je nachdem wie komplex das ist, mit sehr langem Setup-Code überhaupt erstmal hochfahren

[26:07] und dann geben die irgendwelche Sachen zurück, auf die wieder zugegriffen wird.

[26:10] Da muss ein Mock ein Mock zurückgeben, der dann wieder ein Mock zurückgibt und also da wird man irgendwann natürlich auch wahnsinnig.

[26:14] Das heißt, wenn man das irgendwie loswerden kann, die Mocks, bin ich immer dafür.

[26:18] Also wenn ich eine Dependency einfach durch die echte Implementierung ersetzen kann, würde ich das immer bevorzugen,

[26:23] weil ich natürlich diese Implementierung dann gleich mittesten kann.

[26:26] Aber manchmal geht das halt nicht, weil die Dependency zum Beispiel meinetwegen jetzt direkt auf die Datenbank geht

[26:30] und wir das raushaben wollen, okay, dann muss ich es halt rausmocken.

[26:33] Aber so könnte ich zumindest, wenn ich die Unit-Tests starte, die ich ja nicht im EE-Kontext ausführe,

[26:39] diese EE-Magic zumindest, was die Dependency-Injection angeht, ja komplett loswerden.

[26:44] Das heißt, ich arbeite einfach ganz normal mit meinen Beans, mit meinen Pojos.

[26:48] Die haben halt nur ein paar Konstruktorparameter.

[26:50] Aber die baller ich da halt rein.

[26:51] Und ob es jetzt Mocks sind oder die echten, ist dann egal.

[26:53] Hauptsache, ich kann die Klasse im Test schon mal ausführen und brauche halt eben nicht den EE-Kontext dafür.

[26:58] Und dafür kann ich dann, oder muss ich dann eben auch nicht die Equillion-Sachen benutzen,

[27:03] die ja im Application-Server nachher laufen, sondern ich kann wirklich ganz stinknormale Unit-Tests auf Objektebene quasi durchführen.

[27:09] Und das nächste Problem wäre dann, was du gesagt hast, diese Interceptors, die Loggings, die da überall dranhängen.

[27:16] Je nachdem, wie der Logger jetzt da reinkommt, also ich mache es tatsächlich noch so,

[27:19] dass ich wirklich einfach einen Logger mir injizieren lasse.

[27:22] Und inzwischen habe ich auch den Logger als Pflichtparameter in den Konstruktor einfach aufgenommen,

[27:26] genau aus dem gleichen Grund.

[27:27] Das heißt, ich erzeuge mir einfach in meinem Unit-Test einen 0815-Logger.

[27:31] Das kann ja sogar einer sein, der irgendwie im Nirvana verschwindet oder ein simpler Console-Logger oder was auch immer.

[27:36] Also ich benutze da jetzt zum Beispiel SLF4J, einfach die Schnittstelle.

[27:39] Aber es kann ja auch irgendwas anderes sein, ganz egal.

[27:41] Und da kann ich einfach auch im SE-Kontext, in dem die Unit-Tests laufen, einfach so einen Logger instanziieren

[27:47] oder hol mir den von dieser Factory-Methode oder wie auch immer und schmeiß den einfach damit rein.

[27:51] Und dann ist er ja glücklich und dann funktioniert das einfach.

[27:55] Das heißt, ich habe diese EE-Magic mit den Injection-Points und mit den Interceptors vielleicht einfach ausgehebelt,

[28:04] indem ich die Dependencies einfach im Test direkt reingebe.

[28:08] Jetzt ist es natürlich so, wenn es jetzt so ist, dass die Injects direkt an den Attributen hängen,

[28:12] kann man ja, ohne jetzt irgendwas Bestehendes kaputt zu machen,

[28:15] zum Beispiel einfach mal einen Package-Private-Konstruktor in der Klasse hinzufügen,

[28:19] der alle diese Dependencies, die sonst injected werden, hineinbekommt

[28:23] und einfach die Attribute setzt und mehr nicht macht.

[28:26] Wenn er Package-Private ist und die Tests liegen im gleichen Package,

[28:29] dann können die ja diesen Konstruktor nehmen,

[28:31] während der EE-Container den ganz normalen Default-Konstruktor nimmt

[28:34] und über Inject im Nachhinein die Attribute füllt.

[28:36] Aber so könnten zum Beispiel beide Aufrufer, ich sag mal, zufriedengestellt werden.

[28:41] Der Test gibt einfach direkt in den Konstruktor die Sachen rein

[28:44] und im EE-Kontext wird halt der Default-Konstruktor mit den Injects an den Attributen genutzt.

[28:48] So könnte man zumindest erstmal diese Magic, die nötig ist, damit CDI läuft, loswerden,

[28:54] weil du könntest natürlich in einem Test auch einen kompletten CDI-Container hochfahren,

[28:59] was jetzt mit Java EE 8, soweit ich das gelesen habe, auch deutlich einfacher und schneller geht als vorher.

[29:04] Damit habe ich auch schon mal rumexperimentiert, aber ich bin ganz ehrlich,

[29:07] das bietet dir irgendwie kaum Vorteile.

[29:09] Im Gegenteil, die Tests werden wieder super langsam,

[29:11] weil der Container halt auch eine Zeit braucht, um hochzufahren und so weiter.

[29:14] Und er bietet mir auch nicht so richtig Sicherheit.

[29:16] Also, dass es wirklich nachher funktioniert, das ist dann auch wieder die Frage,

[29:20] wenn ich zum Beispiel irgendwas in den Interface injecten lasse

[29:23] und ich habe aus Versehen zwei Implementierungen, er weiß nicht, welche er nehmen soll,

[29:25] dann fällt das zum Beispiel auch gar nicht auf und so.

[29:28] Das heißt, da würde ich lieber auch das, dass das alles funktioniert,

[29:31] nachher in diesem einen großen Integrationstest abdecken

[29:34] und für die Unit-Tests und Integrationstests im Kleinen komplett auf CDI verzichten,

[29:39] weil mir das viel zu langsam wäre.

[29:41] Und das könntest du relativ einfach machen, indem du halt diese Abhängigkeiten explizit machst,

[29:46] über den Konstruktor zum Beispiel.

[29:48] Das heißt, wenn ich dich richtig verstehe, schreibe ich mir in meinem Test-Package

[29:53] einen Package-Private-Konstruktor,

[29:56] übergebe dem die ganzen Attribute, die ich sonst per Inject reinschiebe

[30:01] und rufe dann in meiner Before-Methode vom Test

[30:05] MeinService gleich New MeinService mit dem entsprechenden Konstruktor auf.

[30:10] Ja, zum Beispiel, genau.

[30:12] Damit hättest du die zu testende Klasse relativ einfach instanziiert.

[30:16] Sie kriegt alle Abhängigkeiten von draußen rein.

[30:19] Jetzt mal völlig losgelöst, ob das jetzt Mock sind oder echten Implementierungen,

[30:22] wichtig ist ja erstmal, dass du die zu testende Klasse

[30:25] oder dass du Objekte dieser Klasse so erzeugen kannst,

[30:27] dass du überhaupt mit denen arbeiten kannst

[30:28] und dass es nicht ständig irgendwelche Null-Pointer gibt,

[30:30] weil irgendwelche Injections nicht gesetzt wurden.

[30:32] Und da wäre die einfachste Lösung einfach, alle diese Attribute zu füllen.

[30:37] Ob du dafür jetzt einen Package-Private-Konstruktor hinzufügen musst

[30:40] oder du baust dir halt irgendwie eine kleine, was auch immer,

[30:43] Fabrik-Methode in deiner Test-Klasse, die dann halt den Default-Konstruktor

[30:47] von deiner zu testenden Klasse nimmt und dann nach und nach alle Felder füllt,

[30:50] so sie denn zugänglich sind, wenn sie zum Beispiel private oder sonst was sind,

[30:53] wird es natürlich schwierig.

[30:55] Aber du könntest ja quasi das Erzeugen dieser Objekte ja auch einfach

[30:58] in eine kleine Test-Methode auslagern, die dann einfach der Reihe nach

[31:02] alle Attribute auf ein gültiges Wert, auf ein gültiges Objekt oder so setzt.

[31:06] Das ist ja auch denkbar.

[31:08] Also wenn du den Produktiv-Code gar nicht anpacken willst,

[31:10] dieser Package-Private-Konstruktor, da kann man jetzt auch wieder geteilter Meinung sein,

[31:14] dass ich jetzt meine Produktionsklassen anpassen muss,

[31:17] nur damit ich sie testen kann.

[31:18] Von daher, wenn du das vermeiden möchtest, ginge das auch.

[31:21] Dann baut halt der Test diese Objekte zusammen, muss dann halt eben der Reihe nach

[31:25] quasi das machen, was das CDI automatisch macht und packt da halt an die Attribute

[31:29] die entsprechenden Objekte ran.

[31:31] Würde ja auch gehen.

[31:32] Wichtig ist einfach nur, dass du, sobald der Test startet,

[31:35] halt eben ein gültiges Objekt dieser zu testenden Klasse hast,

[31:38] die keine Null-Pointer mehr schmeißt.

[31:40] Genau.

[31:41] Also das ist ja das, wo man ja dann mit den Mocks halt auch drangeht.

[31:45] Also nein, mit den Mocks nicht, mit den Stubs im Prinzip ja dann.

[31:48] Glaube ich, ist der richtige Begriff.

[31:50] Ja, um diese, die Injections oder die Objekte, die halt sonst vom Application-Server

[31:56] jetzt in unserem Fall bereitgestellt werden, halt selber bereitstellt.

[32:00] Ich muss ja dann für meine Tests dann gegebenenfalls auch nicht alle instanziieren,

[32:04] sondern nur die, wo ich weiß, auf die laufe ich, damit die halt keine Null-Pointer werfen.

[32:08] Ja, ganz genau.

[32:10] Also das mache ich ehrlich gesagt auch so.

[32:11] Ich habe dann vielleicht ein paar kleine Setup-Methoden.

[32:14] Jetzt mal angenommen, ich habe eine Klasse, die hat irgendwie sieben Abhängigkeiten.

[32:17] Ja, kann man jetzt drüber streiten, ob das vielleicht schon zu viele sind.

[32:19] Ja, okay.

[32:20] Angenommen, ich habe jetzt sieben, dann kann es ja sein,

[32:22] dass ich für einen kleinen Use-Case, den ich testen will,

[32:24] auch wirklich nur drei dieser Objekte an den Attributen da gefüllt haben muss.

[32:28] Klar, dann schreibe ich mir eine kleine Methode in meinem Test,

[32:30] die auch einen sprechenden Namen hat.

[32:32] Jetzt das Projekt, an das ich gerade denke, ist zum Beispiel einfach eine Backend-Applikation,

[32:37] die auch mit einer externen Applikation redet und mit deren API reden muss quasi.

[32:41] Und wenn ich mich da jetzt zum Beispiel anmelden muss,

[32:43] ich gebe da irgendwie Credentials rein und erwarte dann,

[32:45] dass da irgendwie eine Session erzeugt wird oder sowas,

[32:47] dann liest sich so eine Methode in meinem Test zum Beispiel,

[32:51] angenommen, Session kann erzeugt werden.

[32:55] Und in dieser Private-Methode in meinem Test

[32:57] werden dann halt irgendwie zwei, drei Mocks hochgefahren,

[33:00] die, wenn ich eine bestimmte Methode aufrufe,

[33:03] zum Beispiel Login mit den Credentials Test und Test,

[33:06] gibt dann halt eine gültige Session oder sowas zurück.

[33:08] Und dann kann ich in meinem Test nachher sagen,

[33:10] also es liest sich dann so, angenommen, Session kann erzeugt werden,

[33:14] dann, keine Ahnung, System.login oder sowas

[33:17] und danach halt Assert Session is not null und Session enthält Username

[33:21] oder was auch immer ich da dann Asserten will.

[33:23] Das heißt, wenn ich das so ein bisschen geschickt auch refaktorisiere

[33:26] und in eigene Methoden packe, dann liesen sich die Tests nachher auch vernünftig.

[33:29] Ansonsten habe ich halt erstmal zehn Zeilen Mock-Code,

[33:32] wo irgendwelche Objekte irgendwas zurückgeben sollen

[33:34] und da blickt nachher dann keiner mehr durch.

[33:36] Und mit diesen kleinen Hilfsmethoden kann man es, ja,

[33:39] schön wiederverwendbar und auch besser lesbar gestalten.

[33:41] Das nutze ich immer ganz gern.

[33:43] Ja, da stimme ich dir vollkommen zu.

[33:45] Sprechende Variablen und Methodennamen

[33:48] sind ja sowieso die größte Herausforderung eines Softwareentwicklers.

[33:50] Und dass auch Testcode oder vielleicht sogar gerade Testcode

[33:55] wartbar sein muss, ist natürlich völlig klar.

[33:59] Wie stehst du zu dem Punkt, was mockst du?

[34:04] Also vielleicht ist die Frage so ein bisschen redundant,

[34:06] aber ich hatte auf einem Konferenzbeitrag,

[34:11] von wem war der denn? Von Gojko Adstik.

[34:15] Ich weiß nicht, ob ich ihn richtig ausspreche.

[34:17] Das war ein Osteuropäer vom Akzent her.

[34:19] Der hatte einen Vortrag über Test-Automation without a headache,

[34:24] five key patterns gehalten.

[34:26] Das war 2006, 16 auf der Norwegian Developers Conference in London.

[34:31] Und der sagte halt unter anderem, man sollte nur Sachen mocken,

[34:35] die man vollständig versteht.

[34:37] Also das sind eigene Komponenten sowie feststehende Standards

[34:41] beziehungsweise Systemeigenschaften, irgendwie Systemuhr oder HTTP-Protokoll.

[34:45] Niemals aber Sachen, die von anderen implementiert sind,

[34:49] zum Beispiel SQL Engine Browser API.

[34:53] Und wenn es geht, keine Legacy-Applications,

[34:57] auch wenn die eigentlich von einem selber sind.

[34:59] Wie stehst du zu dem Thema?

[35:01] Also unterscheidest du da irgendwie, dass du bewusst Sachen rausnimmst

[35:07] oder also aus dem Mocking oder nicht?

[35:11] Oder machst du es wirklich rein nach der Priorisierung?

[35:15] Ich will möglichst viele Unitests haben, die ruckzuck laufen

[35:19] und mocke halt einfach alles.

[35:21] Also ehrlich gesagt beim Mocken, ich mache da so keine harte Unterscheidung.

[35:25] Also die einzige Regel, die ich vielleicht befolgen würde, wäre,

[35:28] ich mocke alles raus, was irgendwelche Grenzen überschreitet.

[35:31] Also was die Infrastruktur beruhigt.

[35:33] Sei es Datenbank, Netzwerk, Festplatte, sowas.

[35:35] Das würde ich grundsätzlich erstmal immer rausmocken.

[35:37] Dabei würde ich auch nicht unterscheiden, wer es implementiert hat.

[35:40] Also ich würde genauso die Java-interne Files, Punkt, Read, irgendwas rausmocken

[35:45] wie irgendeine Log4J, die auf die Platte schreibt

[35:47] oder irgendwas JPA-technisches, was gegen die Daten angeht.

[35:50] Bei mir wäre einfach der Punkt, wenn es die Infrastruktur berührt

[35:54] und die Infrastruktur dazu führen kann, dass mein Test fehlschlägt,

[35:56] sei es, weil die Festplatte voll ist, Datenbankzustand sich geändert hat,

[35:59] Netzwerk down ist, was auch immer, dann mocke ich es erstmal raus.

[36:02] Als nächstes würde ich dann gucken, brauche ich diese Funktionalität,

[36:07] die ich da rausmocke, um die Funktionalität meiner zu testenden Klasse prüfen zu können.

[36:12] Wenn ich zum Beispiel gerade ein, ich habe jetzt ein schönes Projekt bei meinen Azubis,

[36:15] der schreibt einfach einen Datei-Downloader.

[36:18] Den kann ich jetzt schlecht testen, ohne tatsächlich irgendwo eine Datei runterzuladen.

[36:22] Das heißt, da muss ich dann irgendwann auch mal den Mock des, ich weiß es nicht,

[36:26] HTTP-Streams wieder rausnehmen, damit ich überhaupt sicher sein kann,

[36:29] dass er auch wirklich eine Datei runterladen kann.

[36:31] Das mache ich aber erst dann, wenn ich den Rest meiner Verarbeitungslogik

[36:34] komplett ohne diesen Infrastrukturzugriff abgetestet habe.

[36:37] Also Beispiel, es muss irgendwie eine Exception fliegen,

[36:40] wenn irgendein, was auch immer, Timeout kommt.

[36:43] Da kann ich natürlich einen Mock schreiben, der diesen Timeout produziert

[36:46] und ich teste, dass die Exception kommt.

[36:48] Dafür muss ich jetzt nicht fünf Minuten gegen das Internet pollen,

[36:51] um dann ein Timeout zu kriegen.

[36:53] Das kriege ich auf jeden Fall schneller rausgemockt und das läuft dann halt auch super schnell.

[36:57] Da würde ich auf jeden Fall alles, was ich an meiner fachlichen Logik selber entwickeln muss

[37:01] und hinzufügen muss, da würde ich wirklich testgetrieben vorgehen

[37:04] und das komplett Unit testen.

[37:06] Und erst, wenn ich es überhaupt nicht mehr ohne die Infrastruktur irgendwie schaffe,

[37:10] die Funktionalität abzudecken, dann gehe ich in Richtung echter Implementierung.

[37:13] Sei es einer Dabi-Datenbank oder einem echten Netzwerkzugriff oder wie auch immer.

[37:21] Also davon würde ich es abhängig machen und nicht zum Beispiel,

[37:24] wer die Applikation geschrieben hat oder Legacy-Application.

[37:27] Kann man jetzt allein schon darüber streiten, was das denn heißen soll.

[37:30] Also ich finde natürlich auch wichtig, dass man die Dinge, die man da mockt, versteht.

[37:34] Also das kann ich auf jeden Fall unterstreichen.

[37:36] Ich mocke da nicht Sachen raus, weil ich zum Beispiel gar nicht genau weiß,

[37:39] was das Ding da eigentlich macht oder so.

[37:41] Das ist ja super kontraproduktiv.

[37:43] Ich muss ja sogar verstehen, was das Ding macht, was ich mocke.

[37:46] Denn sonst kann ich den Mock ja gar nicht richtig, doofes Wort, set-uppen.

[37:50] Also hier dem Mock sagen, was er eigentlich wann zurückzugeben hat oder zu tun hat,

[37:53] wenn ich aufrufe, was ich da aufrufe.

[37:55] Dafür muss ich auf jeden Fall im Detail verstanden haben,

[37:58] wie überhaupt diese API zum Beispiel da funktioniert, des Loggers meinetwegen,

[38:01] wenn ich den rausmocken will.

[38:03] Also das kann ich nur unterstreichen.

[38:05] Ich wüsste nicht, wie man etwas mocken soll, wenn man gar nicht verstanden hat,

[38:08] wie es funktioniert.

[38:10] Aber sonst mache ich da überhaupt keine Ausnahme.

[38:12] Also alles, was mir einfach beim Test auf die Nase fallen kann, das mocke ich raus.

[38:17] Und da ist für mich eigentlich immer so der Hintergrund Infrastruktur.

[38:20] Alles, was meine JVM verlässt quasi, das mocke ich mir erstmal raus,

[38:24] weil es langsam ist und weil es halt auch fehleranfällig ist.

[38:27] Deswegen.

[38:28] Und wenn ich dann irgendwann sehe, okay, ich komme mit diesen Mocks jetzt nicht mehr weiter,

[38:32] ich habe alles, was ich quasi in plain Java SE testen kann, abgetestet,

[38:36] dann kommt der nächste Schritt

[38:38] und ich nehme jetzt meinetwegen eine echte Datenbank dazu,

[38:41] einen echten Netzwerkzugriff, wie auch immer.

[38:43] Aber dann würde ich mir zum Beispiel schon die Frage stellen,

[38:45] ob ich diese Tests, die dann dazukommen,

[38:48] zum Beispiel in einem separaten Source Folder mache,

[38:50] den ich irgendwie Integration Test nenne,

[38:52] weil ich dann weiß, dass die natürlich auch entsprechend länger dauern,

[38:54] wenn ich irgendwie was gegen das Netzwerk mache

[38:56] und dass die auch ein bisschen fragil sind.

[38:58] Denn wenn das Netzwerk wirklich mal down ist,

[39:00] dann schlägt halt der Testfehl, obwohl ich gar nichts kaputt gemacht habe.

[39:02] Und da würde ich mir dann einfach eine Trennung dieser Tests überlegen,

[39:05] dass ich halt in einem Source Folder zum Beispiel nur die Tests habe,

[39:08] die ich immer in ein paar Millisekunden durchführen kann

[39:10] und die mir auch nicht aus irgendwelchen externen Gründen um die Ohren fliegen können.

[39:13] Und in einem anderen Source Folder habe ich die, die halt länger dauern,

[39:16] wo ich eventuell Abhängigkeiten auf die Infrastruktur habe,

[39:18] die auch mal fehlschlagen können, theoretisch.

[39:20] Das sollte dann nicht passieren, aber man weiß ja nie.

[39:23] Ja, das wäre so mein Vorgehen.

[39:25] Also nein, ich mocke grundsätzlich alles, was mir in die Quere kommt.

[39:28] Das ist auch immer gut. Das ist mal eine klare Aussage.

[39:31] Und unterstreiche auch deinen Aspekt,

[39:33] dass dein primärer Faktor bei der Auswahl die Zeit ist.

[39:38] Auf jeden Fall. Also nichts nervt mich so doll wie langsame Tests.

[39:42] Weil ich weiß nicht, wie oft ich am Tag meine E-Mails checke,

[39:45] während ich auf Tests warte. Das ist gruselig.

[39:47] Wenn das nur zehn Sekunden sind, in der Zeit bin ich einfach tierisch genervt.

[39:51] Und das hält mich super auf und bringt mich auch immer aus meinem Gedankenfluss raus.

[39:54] Also langsame Tests sind das Schlimmste,

[39:56] was mir persönlich bei der Entwicklung passieren kann.

[39:58] Das geht mir richtig auf die Nerven. Das muss ich loswerden.

[40:01] Ja, das mit dem Aus-dem-Fokus-Raus-Kommen, das liest man ja auch gerade, da gab es letztens auch wieder eine Studie zu,

[40:07] irgendwie Kurzunterbrechung kann zwei Stunden Setback bedeuten.

[40:10] Wenn man sich das dann mal vor Augen hält, wie oft man direkt gestört wird, dann arbeitet man da irgendwie 40 Stunden am Tag.

[40:16] Ja, gut, dann habe ich jetzt auf jeden Fall einen stärkeren Standpunkt, wie ich für mich vorgehen möchte,

[40:26] weil ich sehe auch diesen Zeitfaktor als wichtig, als sehr wichtig an, um die fachliche Logik und die Seiteneffekte zu unterdrücken,

[40:36] also sprich den ganzen Regressionsteil.

[40:38] Und das hilft mir dann auch, glaube ich, dass ich mich nicht sofort mit Aquilien auseinandersetzen muss,

[40:44] im Sinne von, dass ich den auch in eine CI-Umgebung kriege.

[40:48] Also ich habe zwar so die grundlegende Aquilien-Konfiguration fertig,

[40:52] aber auch eine Anbindung an eine echte Oracle-Datenbank.

[40:55] Das war auch eine der Bedingungen oder Herausforderungen, die wir in dem Bereich haben,

[41:00] weil mit Sequences und den ganzen Krimskrams und Oracle ist ja dann, wie du selber sagst,

[41:04] ja auch so ein bisschen eigen an der einen oder anderen Stelle, wo man dann nicht irgendwie mal sagen kann,

[41:09] ja, nimm doch eine H2-Datenbank.

[41:11] Das bringt mir dann, glaube ich, wenn ich mich da aufs Mocken konzentriere, schneller einen Erfolg,

[41:19] mit dem ich aber schon, ja, sehr sichere Ergebnisse, glaube ich, erzielen kann.

[41:23] Dann ist jetzt, glaube ich, die Herausforderung bei mir, dass ich das mit dem Mocken halt irgendwie hinkriege.

[41:28] Also dein Tipp mit dem Konstruktor, der könnte mir, glaube ich, da den notwendigen nächsten Schritt bringen.

[41:35] Das habe ich zugegebenermaßen noch nie irgendwovon gehört.

[41:38] Klar, es macht irgendwie Sinn, dass der Application-Server eigentlich nichts anderes macht,

[41:42] aber das halt auch im Test zu benutzen, irgendwie auf die Idee bin ich zum Beispiel noch nicht gekommen

[41:47] und habe davon noch nie irgendwo was gelesen.

[41:50] Ja, das ist tatsächlich die einfachste Möglichkeit, aus diesem EE-Kontext halt rauszukommen.

[41:54] Einfach Objekte rein, fertig.

[41:56] Und wenn du, also ich würde auch zum Einstieg zum Beispiel versuchen, überall, wo es geht,

[42:00] einfach auch echte Implementierung zu nehmen.

[42:02] Also es spricht ja zum Beispiel nichts dagegen, du hast jetzt öfter diesen Logging-Interceptor erwähnt,

[42:05] wenn du im Test einfach einen echten Logger reingibst, wo ist das Problem?

[42:09] Irgendein Konsolenlogger, der läuft so mit, kostet kaum Zeit, das wäre für mich überhaupt kein Problem.

[42:14] Da würde ich den Test auch einfach mit dem echten Logger laufen lassen.

[42:17] Da hätte ich jetzt zum Beispiel gar kein Problem mit, das würde ich jetzt nicht rausmocken.

[42:20] Denn, keine Ahnung, sonst erwartest du irgendwo, dass mit dem Logger irgendwas passiert

[42:24] und dann gibt es wieder einen Null-Pointer, weil du nicht richtig das Setup ausgeführt hast.

[42:28] Das würde ich gar nicht machen.

[42:30] Also wie gesagt, alles, was dir Schmerzen bereitet, kannst du rausmocken.

[42:34] Aber wenn du irgendwo echte Implementierung nimmst, bist du natürlich immer im Vorteil,

[42:37] weil du den Code ja automatisch mittestest, wenn du das als Dependency reingibst.

[42:40] Also Mocking wäre für mich auch immer die letzte Wahl.

[42:43] Wenn ich eine Möglichkeit habe, die echte Implementierung zu nehmen, würde ich die immer bevorzugen.

[42:47] Ganz klar.

[42:48] Ja, wobei du ja schon sagst, dass Tests gegen eine Datenbank ja schon die zweite Stufe von den dreien sind.

[42:56] Also dass du dann für einen Unitest gegebenenfalls auch einfach deine Entity oder deine JPA-Anbindung gegebenenfalls auch erstmal mockst,

[43:06] um schneller das Ergebnis, die konkrete Funktionalität, die du in der Stelle brauchst, zu simulieren

[43:12] und dann in einem zweiten Schritt gegen eine lokale Datenbank gehst und in einem dritten dann gegen eine echte Datenbank.

[43:18] Genau, so würde ich das machen.

[43:20] Im ersten Schritt, also wenn die Entity, da gehe ich jetzt einfach mal davon aus, wenn sie auch noch Geschäftslogik enthält,

[43:24] die Geschäftslogik würde ich komplett ohne irgendeine Datenbank oder sonst was testen,

[43:28] einfach Java SE alles rausmocken oder echte Implementierung reingeben, wo das geht.

[43:32] Dann wäre für mich der nächste Schritt halt diese ganzen Annotationen zu prüfen,

[43:36] also hier, was weiß ich, Column Name und Primary Key und Add Entity selber überhaupt,

[43:41] dass das überhaupt persistiert werden kann und so, ja.

[43:43] Und da kann man jetzt drüber nachdenken, das zum Beispiel mit einer lokalen Datenbank zu machen, mit einer DABI oder so,

[43:49] aber wie du gerade selber schon gesagt hast, in Oracle ist nachher alles anders,

[43:52] weil es zum Beispiel gar keine, ich weiß nicht was, die Datenhypen gibt es nicht oder keine Ahnung was.

[43:56] Also da muss man auch wirklich von Fall zu Fall dann gucken, ob sich das überhaupt lohnt,

[43:59] diesen Schritt noch mit einer lokalen Datenbank überhaupt zu machen

[44:02] oder auch da schon von Anfang an gegen eine echte, zumindest eine echte Oracle zu gehen,

[44:06] wenn es auch die Entwicklungsumgebung ist, ja.

[44:08] Denn sonst habe ich nachher ganz toll getestet, dass das in DABI persistiert werden kann,

[44:12] aber ich deploye es dann in Oracle und nichts läuft mehr.

[44:14] Also die Tests sollen mir ja eine Sicherheit geben, dass es nachher läuft, ja.

[44:16] Also da würde ich schon genau gucken, bringt mir dieser Test wirklich etwas?

[44:21] Und wenn das da nicht der Fall ist, also der Schritt eine kleine, ich sage jetzt mal eine kleine Entwicklungs-Oracle irgendwo hinzulegen,

[44:27] die ich als Target dafür benutze, ist vielleicht teilweise sogar einfacher,

[44:30] als diese DABI-Datenbank lokal erstellen zu lassen.

[44:34] Da muss ja auch das Schema angelegt werden, da müssen die ganzen Migrations vielleicht laufen,

[44:37] ob das überhaupt funktioniert und hin und her.

[44:39] Das ist ja auch etwas, wo man sich erstmal ein paar Stündchen mit beschäftigt,

[44:41] bis man so eine lokale DABI-Datenbank überhaupt am Laufen hat im Test.

[44:44] Da ist es vielleicht einfacher direkt zu sagen, komm DBA, leg mir mal ein kleines Schema an,

[44:49] was wir auch, da brauchen wir ja keine Daten, also da muss ja nur das Schema da sein quasi,

[44:53] um zu gucken, ob das persistiert werden kann, ja.

[44:55] Das ist dann vielleicht der bessere Weg, als nochmal diesen zweiten Zwischenschritt zu gehen.

[45:01] Wie und unter was für einem User, also machst du so Datenbank-Tests?

[45:07] Also sprich, ich weiß nicht, vielleicht habt ihr auch einfach in den Anwendungen einen Datenbank-User,

[45:14] der eh immer alles darf.

[45:15] Wir unterscheiden da zum Beispiel, also unsere technischen User haben auch eingeschränkte Rechte,

[45:19] um halt nur das machen zu können, was sie dürfen oder was sie dürfen sollen,

[45:24] womit dann aber halt auch viele Sachen, die man gerade zum Aufbau einer Testumgebung

[45:30] oder eines Testdatenbestands und zum Aufräumen nicht hat.

[45:33] Jetzt gibt es bei Equillion die Möglichkeit, das mit zwei unterschiedlichen Persistence-Units zu machen.

[45:40] Also einmal die, die man in der Equillion-XML als DW-Unit, die die Data-Source angibt

[45:47] und dann während der Geschäftslogik auf die Persistence-Unit und die darin definierte Data-Source

[45:53] über den Application-Server zu greifen, das funktioniert,

[45:57] sodass ich mich dann gegebenenfalls bei diesem Zwischenschritt eventuell auch schwer tun würde,

[46:03] weil da habe ich ja dann auf jeden Fall einen künstlichen User, der mehr darf,

[46:07] als er eigentlich in der späteren Logik darf.

[46:09] Ja, das würde ich tatsächlich genauso machen.

[46:12] Also wenn ich jetzt dieses Beispiel mal genau aufgreife, ich habe jetzt mal eine App,

[46:15] die will ich gegen eine echte Oracle-Datenbank testen.

[46:18] Ich würde es auch hier wieder davon abhängig machen, dass die Tests möglichst schnell laufen.

[46:23] Das heißt, ich würde den Test jetzt erstmal im SE-Kontext ausführen.

[46:27] Ich würde mir zum Beispiel einfach irgendeine JPA-Implementierung nehmen.

[46:30] Ich nehme mal Eclipse Link zum Beispiel oder Hibernate kann man auch lokal einfach als dependency reinhängen

[46:34] und ich habe dann von Anfang an darauf geachtet, aber du hast es schon gesagt,

[46:39] dass es bei euch auch so ist, dass zum Beispiel eure Repositories oder die Entity selber,

[46:43] wer auch immer da persistiert, zum Beispiel den Entity-Manager einfach injected bekommt

[46:47] und wenn man es hinkriegt, dass die Klassen, die diesen Entity-Manager nutzen,

[46:50] den nicht nur injected bekommen, sondern auch hier wieder vielleicht diesen kleinen Trick

[46:54] mit dem Konstruktor angeht, sodass man diese Objekte zu Laufzeit auch einfach selber

[46:58] mit einem Entity-Manager versorgen kann, dann lasse ich in meinen Tests einfach

[47:02] zum Beispiel mit Eclipse Link einen eigenen Entity-Manager hochfahren im SE-Kontext,

[47:07] den ich dann einfach in den Before-Methoden in meine zu testenden Objekte reingebe

[47:11] und dann habe ich trotzdem nicht den ganzen EE-Kontext, den ich hochfahren muss,

[47:15] sondern nur diesen einen JPA-Kontext zum Beispiel und kann damit dann gegen

[47:19] eine echte Datenbank testen und ich würde dann tatsächlich das so machen,

[47:25] dass ich in dem Source-Folder für diese Tests eine eigene Persistence-XML

[47:29] zum Beispiel ablege und ich, also was ich auf keinen Fall haben will,

[47:32] ich weiß nicht, ob du das jetzt im Hintergrund hattest, dass ich zum Beispiel

[47:35] irgendwelche benannten Persistence-Units irgendwo in meinem Code sehe

[47:39] und dann irgendwo unterschieden werden muss, welche ich da gerade nutze,

[47:42] das heißt, ich will auf keinen Fall in meinem Produktionscode irgendeine Unterscheidung

[47:45] von Persistence-Units haben. Ich will, dass der ja gar nichts davon weiß,

[47:48] dass es die überhaupt gibt. Deswegen habe ich dann eine zweite Persistence-XML

[47:51] in meinem Source-Folder als Ressource liegen, die dann mit einem technischen User,

[47:54] ja, eventuell auch mit erweiterten Rechten, aber ja nur gegen eine Entwicklungsdatenbank,

[47:58] das heißt, der kann ja völlig lokal auf dieser Datenbank sein, konfiguriert ist

[48:02] und dann hole ich mir im SE-Kontext den Entity-Manager gegen die Entwicklungsdatenbank

[48:06] mit einem technischen User mit erweiterten Rechten und lasse damit die Tests durchlaufen.

[48:11] Ja, also gut, wir gehen halt da, also ich unterstütze das vollkommen,

[48:16] dass wir nicht irgendwo drinstehen haben wollen, nutze jetzt den und den Entity-Manager

[48:22] oder ein If-Else, sonst irgendwas, abhängig von der Umgebung.

[48:26] Wir geben halt sowas auch von außen alles mit, indem wir die Bordmittel des Application-Servers nehmen

[48:32] und dann über einen festgelegten JNDI-Namen, der nicht umgebungsspezifisch ist,

[48:39] sondern halt Applikation-Server einmalig ist, darauf zugreifen,

[48:44] dass wir eben völlig unabhängig von der Umgebung sind, das ist natürlich klar.

[48:48] Ja, genau so würde ich es auch letztlich dann implementieren und da musst du halt nur dafür sorgen,

[48:52] dass du im Test halt ohne diesen JNDI-Lookup da klarkommst, das heißt,

[48:56] wenn du da deine Objekte wieder quasi Dependency Injection ready machst

[49:01] über einen Setter oder Konstruktor oder was auch immer,

[49:04] dann kannst du dir halt dieses ganze Zeug EE halt sparen und das ganz normal mit SE testen.

[49:10] Ja, das muss ich dann nochmal abwägen, wobei, wie gesagt,

[49:16] wenn ich eventuell diesen zweiten Schritt E überspringe und direkt mit einer echten Datenbank teste,

[49:22] muss ich dann, glaube ich, wenn ich dann mal da drin bin und so weit bin,

[49:26] mir dann auch Gedanken machen, ob es denn dann noch notwendig ist

[49:30] dass ich die Bordmittel, die Equillion dann mitbringt, an der Stelle nicht nutzen kann,

[49:34] weil ich halt schon getestet habe, dass die Data Source,

[49:39] die für das Setup und für das Cleanup am Ende benutzt wird,

[49:43] eine andere sein kann als die, die ich meiner Business-Logik über den Application-Server gebe.

[49:50] Ja, und da geht es nämlich schon los, also das Ding musst du in Equillion dir dann auch quasi zusammenbauen,

[49:55] das heißt, du brauchst irgendwo eine zweite Persistence-XML,

[49:57] die du dann, wenn du das Deployment-Archiv mit Equillion zusammenschraubelst,

[50:01] die musst du dem halt dann quasi unterjubeln.

[50:04] Das heißt, wenn du das zum Beispiel nicht richtig machst,

[50:06] dann kann der Test dann auch mal gegen die Produktion laufen.

[50:08] Das darf natürlich nicht passieren, ja, und das könntest du eliminieren,

[50:12] indem du halt wirklich nur die Persistenz-Logik mit so im SE-Kontext

[50:17] mit deinem eigenen Entity-Manager testest.

[50:19] Du kannst es auch mit Equillion machen, keine Frage,

[50:21] aber auch hier wäre wieder die Laufzeit mein Problem.

[50:23] Das Equillion ist halt nochmal wirklich deutlich langsamer

[50:26] als selbst ein kompletter Hibernate-Kontext, den du dir völlig lokal erzeugst.

[50:30] Also da würde ich einfach gucken, wie lange das braucht

[50:32] und dieses Zusammenfrickeln der Equillion-Tests.

[50:35] Also ich persönlich würde die Datenbank-Anwendung gegen eine echte Oracle testen,

[50:40] ja, aber nicht mit Equillion noch zusätzlich drauf,

[50:43] weil da musst du halt ein komplettes Deployment machen, was nochmal wieder lange dauert.

[50:46] Das würde ich mir einfach angucken.

[50:49] Wenn dir das schnell genug ist, dann kannst du es direkt mit Equillion machen.

[50:52] Ansonsten ist die Alternative halt, den Entity-Manager einfach selber zu erzeugen.

[50:56] Das geht auf jeden Fall noch schneller als ein Deployment.

[50:59] Also ich glaube, das muss ich dann an dem Punkt mir angucken im Detail.

[51:05] Deine Argumentation ist natürlich vollkommen logisch und nachvollziehbar.

[51:09] Das muss ich dann einfach, wenn ich ein bisschen mehr Erfahrung mit der ganzen Thematik habe.

[51:13] Mein Fokus wird auf jeden Fall am Anfang sein,

[51:15] dass ich, ja, ich sag mal, mit Unit-Tests überhaupt meine Fachlogik abgebildet kriege

[51:21] und diesen ganzen Dependency-Injection-Kram mal außen vor lassen kann,

[51:26] damit ich erstmal mit, ich sag mal, einem überschaubaren Aufwand

[51:29] möglichst meine Tests erstmal in ihrer Anzahl explodieren lassen kann.

[51:34] Das würde ich auch exakt so empfehlen.

[51:36] Also du hast den meisten Benefit sicherlich, wenn du die Fachlichkeit abtestest.

[51:40] Also das, ja, wie gesagt, die EE-Magic, normalerweise läuft die, ja,

[51:45] wenn jetzt, ihr habt ja auch schon eine Applikation, die fertig ist, ja,

[51:48] der Overhead, um das ganze Ding jetzt wirklich automatisiert deploybar zu machen

[51:53] und dann so testen und weh, um dann nachher rauszufinden, dass 1 plus 2 gleich 3 ist,

[51:56] also würde ich mir niemals antun.

[51:58] Ich würde lieber versuchen, von innen die Objekte vielleicht zur Not auch noch so aufzubrechen,

[52:03] dass sie testbarer sind.

[52:05] Vielleicht sind die Klassen auch schon zu groß, haben zu viele Abhängigkeiten

[52:07] und deswegen wird das Mocking auch so schwierig.

[52:09] Also wenn ich zum Beispiel in den Unit-Tests für die Klassen einfach so viele Mocks erzeugen muss,

[52:14] dass ich wirklich, ich sag jetzt mal, übertreibe jetzt mal,

[52:16] seitenweise irgendwelche Setup-Geschichten machen muss, damit es überhaupt funktioniert,

[52:19] dann heißt das eigentlich eher, dass die Klasse, die ich teste, mit einfach viel zu vielen Abhängigkeiten hat

[52:23] und dass es irgendwie reduziert werden muss.

[52:25] Daher kommt vielleicht auch, dass Leute sagen, Mocking muss gleich wieder abgeschafft werden,

[52:28] weil es einfach natürlich enorm schwierig ist, das alles überhaupt lauffähig hinzukriegen,

[52:32] wenn meine Klasse erstmal 7 Mocks braucht, um überhaupt zu funktionieren, ja.

[52:36] Das ist für mich auch immer ganz gut, da muss ich mir selber auch immer auf die Finger klopfen,

[52:40] wenn ich irgendwann am Ende 30 angenommen Sternchen-Methoden habe in meinem Test,

[52:45] dann weiß ich, ich habe eigentlich schon irgendwas falsch gemacht,

[52:47] weil das sind einfach so komplexe Setups, da muss ich die Klasse einfach auseinanderreißen

[52:50] und dann wird der Test auch wieder leichter und dann brauche ich auch nur noch ein, zwei Mocks

[52:53] und dann verstehe ich das am Ende auch.

[52:55] Ich habe auch schon selber leider die Erfahrung gemacht, wenn man da nicht drauf achtet

[52:59] und das irgendwann auseinanderreißt, dann habe ich wirklich so ein komplexes Setup,

[53:02] wo ich selber am Ende nicht mehr richtig durchsteige, warum das jetzt so sein muss,

[53:07] damit es dann funktioniert und dann bringen mir die Tests am Ende auch nicht mehr viel,

[53:10] wenn ich selber nicht verstehe, was sie tun.

[53:12] Also das ist nur ein Tipp aus der Praxis von mir.

[53:15] Wenn das Mock-Setup zu umfangreich wird, ist die Klasse einfach zu groß

[53:20] oder hat zu viele Abhängigkeiten, die muss auseinandergenommen werden.

[53:22] Ja, da sind wir ja bei der Thematik Clean Code und Refactoring

[53:27] und den ganzen Diskussionsgrundlagen und Büchern und sonst was,

[53:32] was es zu dem Thematik gibt, wartbarer Code und was habe ich denn gestern noch mal programmiert

[53:37] oder was habe ich denn vor der Mittagspause programmiert und ich habe jetzt Feierabend.

[53:41] Klar, natürlich, das soll jetzt aber nicht, glaube ich, Thema hier werden.

[53:47] Da sind wir uns aber auf jeden Fall einig.

[53:50] Ja, von meiner Seite aus, soweit ich das jetzt betrachten kann oder bewerten kann,

[53:58] ohne es natürlich jetzt parallel schon hier gecodet zu haben.

[54:01] Dankeschön. Es hat mir auf jeden Fall einen guten Einblick verschafft,

[54:05] wie ich meinen Fokus setzen sollte und auch wie ich die Sachen denn angehen kann,

[54:11] um vielleicht schneller oder einfacher zu einem ersten Erfolg,

[54:14] an den sich dann viele hoffentlich anschließen, gelangen kann.

[54:17] Kein Problem. Wenn du da noch irgendwelche weiteren Fragen hast

[54:20] oder hast mal einen kleinen Codeschnipsel oder irgendwas, kannst du gerne Bescheid sagen.

[54:24] Also ich mache auch aktuell tatsächlich auch im Java EE-Umfeld immer noch weiter

[54:28] und jetzt aktuell REST-Anwendung und JSF-Frontend und das wird alles komplett automatisch getestet,

[54:35] bis hin auch zum Deployment, was ja auch alles geht mit Java-Bordmitteln.

[54:39] Das ist ja wirklich die Infrastruktur, die da ist, die muss man einfach nur nutzen.

[54:43] Aber aus eigener Erfahrung, also gerade wenn man noch nie zum Beispiel mit Equillion gearbeitet hat,

[54:47] es hat mich auch enorm viel Zeit gekostet, das vernünftig testbar hinzukriegen,

[54:51] weil man auch die Applikation an sich so bauen muss, dass man einfach vieles auch austauschen kann.

[54:55] Zum Beispiel, was weiß ich, eine Restant Shell, der muss man halt mal eben zur Laufzeit sagen können,

[54:59] dass sie jetzt unter einer anderen URL erreichbar ist, damit ich das vernünftig testen kann und sowas.

[55:02] Und wenn man das nicht von Anfang an einbaut in die Applikation, wird es sehr schwierig,

[55:05] das im Nachhinein reinzukriegen. Von daher würde ich auch durchaus nochmal die Empfehlung aussprechen,

[55:09] vielleicht nicht mit Equillion direkt anzufangen, sondern erstmal den Rest zu testen.

[55:12] Und da gibt es ja auch wirklich Quick Wins, wo man, sage ich mal, den Großteil seiner Applikationslogik

[55:17] schon mal unter Test kriegt und den ganzen Technik-Kram drumherum,

[55:21] der ja jetzt schon bei euch seit Monaten oder Jahren schon funktioniert,

[55:25] den kann man dann vielleicht als letztes angehen, weil das ist wirklich super fehleranfällig

[55:29] und kann sehr frustrierend sein und auch einfach lange dauern, bis das vernünftig läuft.

[55:33] Das ist meine persönliche Erfahrung. Ja, okay, dann, wenn du tatsächlich jetzt keine weiteren Fragen mehr hast,

[55:39] dann sind wir ja schon fertig quasi.

[55:41] Ja, also ich wüsste jetzt nicht. Also die Fragen werden sich sicherlich dann nochmal ergeben.

[55:46] Gerade wie ich das dann einfach technisch umsetze, muss ich einfach dann ein bisschen üben.

[55:52] Aber daran soll es ja nicht scheitern.

[55:54] Also das ist ja dann wahrscheinlich auch etwas, was man irgendwie einmal zum Laufen kriegt

[55:58] und dann sich denkt, ja, warum habe ich dafür jetzt fünf Stunden gebraucht?

[56:01] Und danach nutzt man es ja einfach und schreibt es in der Zukunft dann einfach runter

[56:08] und kommt ja dann immer noch schneller zu einem Erfolg.

[56:12] Richtig. Nur die initiale Hürde, die ist auf jeden Fall einmal da, ja.

[56:16] Ja, dann würde ich einfach zum Abschluss nochmal so ein paar ganz allgemeine oder vielleicht ein, zwei allgemeine Fragen stellen.

[56:21] Du hast jetzt schon gesagt, um dich ins Thema einzubeiten, hast du auch viele Beiträge gelesen oder Videos oder sonst irgendwas.

[56:25] Hast du dir vielleicht irgendwie ein, zwei Ressourcen rund um das Thema, die du dir jetzt empfehlen kannst?

[56:29] Also du hast gesagt, einiges hat dich eher verwirrt, aber war da vielleicht irgendwie ein schönes Video dabei

[56:34] oder irgendein Buch oder irgendwas, wo du sagst, Mensch, das hat mir echt gut gefallen.

[56:37] Da habe ich was mitgenommen. Das könnten wir vielleicht nochmal angucken.

[56:40] Kann ich jetzt ganz ehrlich gesagt gar nicht so sagen.

[56:43] Also die meisten Blogs, Posts habe ich mir jetzt auch gar nicht großartig gespeichert.

[56:50] Was ich halt sehr interessant fand, war dieses, war dieser eine Konferenzbeitrag von den Test Automation Without a Headache.

[56:59] Jetzt nicht unbedingt wegen der Mockfrage, sondern weil da auch einige andere interessante Aspekte sind.

[57:05] Den fand ich einfach gut.

[57:07] Und jetzt sogar relativ aktuell gab es einen Artikel von dem Martin Fowler, der ja auch relativ bekannt ist im Testumfeld,

[57:16] der die ganze Thematik Stubs, Mocks, Spies und sonst irgendwas mal sehr ausführlich erläutert hat,

[57:26] was denn was ist und was eben nicht was ist.

[57:29] Den fand ich auch sehr, sehr gut.

[57:31] Und da habe ich dann auch festgestellt, dass man viel liest, wo Begriffe eigentlich falsch benutzt werden

[57:37] und man sie auch oder ich zumindest so im Alltag oft Begriffe falsch benutze.

[57:43] Und jetzt dann bei meiner Wortwahl doch mehr darauf achte, ob ich jetzt Mock sage, ob ich Stubs sage oder irgendwas anderes.

[57:53] Die Unterschiede sind klein an einigen Stellen, aber dann auf der anderen Seite, wenn man darüber nachdenkt, auch deutlich größer.

[58:00] Jetzt, dass man die Begriffe nicht irgendwie so nu benutzen sollte.

[58:03] Da hast du völlig recht. Also mir rutscht eigentlich, ich habe auch die ganze Zeit jetzt immer Mock gesagt,

[58:06] auch wenn es im Detail wahrscheinlich gar nicht immer nötig ist und wahrscheinlich eher Stubs sind.

[58:10] Für Fake-Objekt nutze ich einfach so Mock, obwohl das natürlich eigentlich gar nicht richtig ist.

[58:15] Mocks zeichnen ja quasi die Interaktion mit ihnen auf und das braucht man in den meisten Fällen ja gar nicht.

[58:20] Wenn man testet, insbesondere was du jetzt hattest, Dependency Injection,

[58:22] da muss ich eigentlich eher die Stub-Implementierung mit fixen Werten reingeben und nicht irgendwie aufzeichnen,

[58:28] dass irgendwo eine bestimmte Reihenfolge von Methodenaufrufen durchgeführt wurde.

[58:31] Also da kann man im Detail sicherlich das nochmal auseinandernehmen.

[58:34] Da hast du recht. Ich hätte wahrscheinlich auch andere Wörter benutzen müssen.

[58:38] Ja, aber wenn man sich damit näher beschäftigt, ist das auch super interessant, dass es die Unterscheidung gibt und auch super sinnvoll.

[58:47] Aber es wird halt so im Allgemeinen von Mocks gesprochen, obwohl es in den meisten Fällen eigentlich gar kein Mock ist.

[58:54] Das stimmt. Ich weiß nicht, hast du schon eine Idee, was für ein Mock-Framework du benutzen wirst? Vielleicht Mockito?

[59:00] Ja, ich tendiere im Moment jetzt zu Mockito. Da findet man doch relativ viel Dokumentationen zu oder Tutorials zu,

[59:08] dass das glaube ich jetzt für den Einstieg eine ganz gute Einstiegsvariante ist.

[59:16] Du hattest es ja auch in deinem Java-Land-Konferenzbeitrag auch erwähnt. Und dann noch irgendwas mit der Zitrone, kann ich mich noch daran erinnern.

[59:24] Ja, genau. Citrus, ja. Aber Mockito kann ich auch empfehlen. Ich wollte nur deswegen sagen, weil da nämlich zum Beispiel auch gar nichts zwischen Stub und Mock unterschieden wird.

[59:32] Die Methode, um das Ding zu erzeugen, heißt auch Mock. Das heißt, egal was ich da mache, es heißt immer Mock. Deswegen hat es bei mir auch so eingebrannt, die Dinger Mocks.

[59:40] Ja, genau. Das ist mir auch schon aufgefallen, als ich meine ersten Schritte damit gemacht habe. Und ganz ehrlich, mir ist es in der Regel auch vollkommen egal, wie das Ding jetzt heißt, wenn ich verstehe, was es denn machen soll.

[59:55] Also ob es jetzt Behaviour simuliert oder ob es mir nur Sturen…

[1:00:00] einen Wert zurückgibt, wenn ich es aufrufe, oder einfach nur da ist, um keine Null-Pointer-Exception zu werfen,

[1:00:07] ist mir für das praktische Doing vollkommen egal, wie ich es dann nenne.

[1:00:12] Nur man sollte sich eigentlich, wenn man ein bisschen eigene Ansprüche hat,

[1:00:17] sollte man sich schon natürlich damit auseinandersetzen, dass ein Mock nicht unbedingt ein Mock ist.

[1:00:22] Das stimmt. Da kann ich nur zustimmen. Hauptsache, es läuft in der Praxis, dann ist es am Ende egal, wie es heißt.

[1:00:28] Aber ich finde es auch mal wichtig, das sage ich mal dazu, wie es auch immer, benutzt nichts, was ihr nicht verstanden habt,

[1:00:32] von daher finde ich es auch gut, die Begriffe auseinanderhalten zu können, definitiv.

[1:00:36] Dann vielleicht meine allerletzte Frage, hast du denn vielleicht ganz allgemein rund um die Programmierung noch irgendeine Empfehlung bezüglich einer Quelle,

[1:00:43] vielleicht ein nettes Buch oder irgendwas, so dein All-Time-Favorite, was jeder Entwickler unbedingt mal gelesen, gesehen, gehört haben muss?

[1:00:50] Auch wenn ich mich jetzt wahrscheinlich bei ziemlich vielen unbelied mache,

[1:00:54] ich finde Clean Code von dem Martin sehr wichtig.

[1:01:00] Ich teile nicht alles, was er schreibt, aber einen Großteil,

[1:01:04] weil ich es einfach extrem wichtig finde, wartbaren und auch leslichen Code zu haben.

[1:01:10] Es hat auch gewisse Kämpfe bei uns gegeben, sage ich mal,

[1:01:14] was statische Codeanalyse, Checkstyles und sonst irgendwas angeht,

[1:01:18] aber ich habe mich durchgesetzt und inzwischen verstehen die Leute, dass es sinnvoll ist.

[1:01:22] Also auf Codequalität und Wartbarkeit lege ich sehr großen Wert,

[1:01:26] weil ich einfach gemerkt habe, dass das sehr, sehr nützlich ist.

[1:01:30] Ja, und dann, da kann ich jetzt nicht speziell ein Buch oder so nennen,

[1:01:34] aber alles, was mit Continuous Integration und Automatisierung im Allgemeinen zu tun hat,

[1:01:42] ist einfach so viel wert, weil man sich damit einmal auseinandersetzt

[1:01:46] und dann ab einem gewissen Punkt einfach nur noch Benefit hat.

[1:01:50] Ja, super, kann ich nur unterstreichen.

[1:01:52] Also einmal das Buch, ich lese es gerade tatsächlich zum zweiten Mal.

[1:01:55] Meine Azubis machen da gerade einen Buchclub mit mir und CI, auch das gehört quasi

[1:02:00] auch zu meinem Tagesgeschäft dazu, alles Mögliche zu automatisieren bei uns

[1:02:03] und ja, Quillen, das ganze Zeug, über das wir heute gesprochen haben,

[1:02:06] ist ja letztlich ein Schritt in so einer Build-Pipeline.

[1:02:09] Also von daher enorm wichtig und ja, ich kann das auch nur unterstreichen.

[1:02:13] Was soll man sich die Mühe da täglich händisch machen,

[1:02:17] damit der Build-Prozessor genauso gut wiederholbar auf Knopfdruck machen kann?

[1:02:21] Ja, und vor allen Dingen der Fokus darauf, Plattformen unabhängig zu entwickeln

[1:02:28] beziehungsweise seine Applikationen-Plattformen unabhängig zu machen.

[1:02:32] Wir hatten früher ganz viele Dependencies, die irgendwie manuell

[1:02:36] in den Classpath gelegt werden müssten und Abhängigkeiten zu anderen Java-Projekten.

[1:02:43] Das ist teilweise dem IBM-Process-Server geschuldet, da kann man auch nicht so viel dann machen.

[1:02:49] Aber gerade was klassische Java-Enterprise angeht, seit wir auf Maven umgestellt haben,

[1:02:53] kann ich jedem Entwickler bei uns sagen, hier ist die Git-URL,

[1:02:57] zieh es dir raus, importier es in Eclipse und fang an.

[1:02:59] Und früher dann erstmal, was muss ich denn jetzt noch einbinden

[1:03:03] und konfigurieren und sonst irgendwas, das fällt halt dadurch alles weg

[1:03:07] und das sind einfach, auch wenn sie vielleicht gar nicht so auffallen,

[1:03:11] sehr viele Sachen, die extrem viel Zeit sparen, die gleichzeitig den Code

[1:03:15] oder das Projekt in dem Fall übersichtlich und wartbarer machen

[1:03:19] und auch Fehler finden.

[1:03:23] Nur weil ein Maven-Projekt lokal baut, heißt das noch lange nicht,

[1:03:27] dass der es auf dem CI-Server baut, wenn man irgendwie vergessen hat,

[1:03:31] eine Datei einzubinden oder sonst irgendwas.

[1:03:35] Diese Plattform-Unabhängigkeit und Automatisierung

[1:03:39] ist einfach für die Wartbarkeit und dadurch für die Zeitersparnis

[1:03:43] extrem wertvoll, meiner Erfahrung nach.

[1:03:45] Das kann ich auch nur bestätigen, gerade wenn man noch Entwickler hat,

[1:03:47] die irgendwie, der eine arbeitet auf Mac, der andere auf Linux,

[1:03:49] der andere auf Windows.

[1:03:51] Da will man sich nicht um irgendwelche Projekt-Setups noch kümmern.

[1:03:53] Das macht das Build-Tool dann.

[1:03:55] Das kann ich nur bestätigen.

[1:03:57] Ja, okay, das war ein schönes Schlusswort.

[1:03:59] Passt auch gut zum Thema.

[1:04:01] Wie beim Testen ist immer oder sollte meiner Meinung nach immer Teil

[1:04:03] so eines automatischen Prozesses sein, um zu gucken,

[1:04:05] dass am Ende auch alles geklappt hat.

[1:04:07] Ja, von mir aus gibt es da nichts mehr dazu zu fügen,

[1:04:11] außer vielleicht eine Sache.

[1:04:13] Sollte jemand mit dir in Kontakt treten wollen,

[1:04:15] vielleicht auch mal eine Frage stellen oder Anregungen geben wollen,

[1:04:17] kann man dich irgendwo online finden oder eher nicht so?

[1:04:19] Eher nicht so.

[1:04:21] Also, Facebook halte ich dann doch eher privat.

[1:04:25] Und ansonsten, bei Stack Overflow bin ich.

[1:04:27] Also, wenn ihr die richtige Frage stellt, dann lese ich sie vielleicht.

[1:04:29] Wobei ich jetzt auch nicht so ein Power-User da bin.

[1:04:33] Also, ich lese da auch mehr, als dass ich da schreibe.

[1:04:36] Nö.

[1:04:38] Wir haben ganz viele offene Stellen.

[1:04:40] Also, wenn ihr euch bewerben wollt,

[1:04:42] dann kommt ihr sicherlich gleich mit mir in Kontakt,

[1:04:46] wenn ihr zu mir kommt.

[1:04:48] Nee, also, ich bin jetzt eher nicht jemand,

[1:04:52] der groß die Social Medias dieser Welt,

[1:04:55] Networke dieser Welt aktiv betreibt.

[1:04:59] Okay, das ist kein Problem.

[1:05:01] Es geht auch so.

[1:05:03] Wenn jemand Fragen hat, kann man es ja auch als Kommentar

[1:05:05] unter die Show Notes der Episode packen,

[1:05:07] wo ich dann übrigens auch noch alle Links ergänze,

[1:05:09] über die wir vielleicht noch gesprochen haben.

[1:05:11] Ja, von daher, also, kein Thema.

[1:05:14] Dann sage ich zum Abschluss nochmal vielen Dank,

[1:05:16] dass du dir Zeit genommen hast.

[1:05:18] Ich hoffe, ich konnte dir auch ein bisschen weiterhelfen.

[1:05:20] Ich fand es auf jeden Fall auch mal interessant zu sehen,

[1:05:22] was du für Fragestellungen hast,

[1:05:24] um in die Sache einzusteigen.

[1:05:26] Ich finde es für mich auch ganz hilfreich,

[1:05:28] weil meine Azubis natürlich auch immer vor der gleichen Frage stehen.

[1:05:30] Wie fangen wir denn jetzt an?

[1:05:32] Jetzt muss ich 37 Frameworks installieren,

[1:05:34] oder wo geht es los?

[1:05:36] Von daher, deswegen war es mir auch ein Anliegen,

[1:05:38] dass wir das hier quasi einmal aufzeichnen,

[1:05:40] damit auch andere so ein bisschen was davon haben,

[1:05:42] weil ich glaube, dass viele andere Entwickler

[1:05:44] sich auch diese Frage stellen.

[1:05:46] Das kann ich für meine Unternehmen genauso bestätigen.

[1:05:48] Da wird auch nicht 100% Code Coverage

[1:05:50] durch alle Kollegen hergestellt.

[1:05:52] Da gibt es auch auf jeden Fall immer noch Lernbedarf,

[1:05:54] sage ich mal.

[1:05:56] Von daher fand ich es ganz toll,

[1:05:58] dass du auch zugestimmt hast,

[1:06:00] und ich habe auch ein paar Fragen gestellt.

[1:06:02] Vielen Dank für deine Zeit, muss ich ja sagen.

[1:06:04] Ich war ja derjenige mit den Fragen.

[1:06:06] Ich finde es auch gut,

[1:06:08] dass du dich da so engagierst für die Ausbildung.

[1:06:10] Ich habe es ja selber genossen,

[1:06:12] eine Ausbildung,

[1:06:14] also jetzt nicht bei dir,

[1:06:16] aber eine Ausbildung als Fachinformatiker.

[1:06:18] Das klingt jetzt vielleicht ein bisschen eingebildet,

[1:06:20] aber wenn ich mir Leute angucke,

[1:06:22] die aus der Ausbildung kommen,

[1:06:24] mit denen kann man erst mal mehr anfangen

[1:06:26] als Leute, die von der Schule und dem Studium kommen.

[1:06:28] Ich habe beides gemacht. Ich habe ja auch studiert.

[1:06:30] Aber so eine Ausbildung ist wichtig,

[1:06:32] dass man die praktischen Ansätze hat,

[1:06:34] und dann steht man,

[1:06:36] genau wie du sagst, oft vor dem Punkt,

[1:06:38] wie fange ich denn an?

[1:06:40] Es geht meistens gar nicht darum,

[1:06:42] die Herausforderung beim eigentlichen implementieren,

[1:06:44] sondern wirklich mit dem,

[1:06:46] wie fange ich denn an?

[1:06:48] Ja, das kann ich nur bestätigen.

[1:06:50] Einfach so ein kleiner Denkanstoß reicht ja schon.

[1:06:52] Vielleicht einfach für dich diese Konstruktorgeschichte

[1:06:54] einfach mal ausprobieren,

[1:06:56] weil so ein Knoten geplatzt ist,

[1:06:58] das hat man ja vielleicht mal.

[1:07:00] Kann ich nur hoffen, dass das funktioniert.

[1:07:02] Dann sind wir für heute fertig,

[1:07:04] und wenn du noch irgendwelche Fragen hast,

[1:07:06] kannst du dich auf jeden Fall melden.

[1:07:08] Ja, mache ich. Vielen Dank nochmal.

[1:07:16] Das war mein Interview mit Matthias Bünger.

[1:07:18] Ich hoffe, es hat dir ein bisschen Spaß gemacht,

[1:07:20] und es war einiges für dich dabei,

[1:07:22] rund ums Thema Testen.

[1:07:24] Wenn du vielleicht wirklich in Java unterwegs bist,

[1:07:26] hast du da hoffentlich einiges mitgenommen

[1:07:28] für deine Praxis.

[1:07:30] Ich fand das Format heute auch super interessant,

[1:07:32] ganz witzig zu sehen,

[1:07:34] wenn man auf der anderen Seite ist

[1:07:36] und Fragen beantworten muss.

[1:07:38] Und für dich vielleicht auch ein Hinweis,

[1:07:40] wenn du irgendwelche anderen Fragen hast,

[1:07:42] die du glaubst von mir beantwortet bekommen zu können,

[1:07:44] dann schreib mir doch einfach eine Mail,

[1:07:46] stell deine Frage,

[1:07:48] und ja, vielleicht machen wir mal

[1:07:50] so ein neues Podcast-Format daraus.

[1:07:52] Du stellst mir eine Frage oder mehrere Fragen,

[1:07:54] und wir schnacken einfach mal ganz locker

[1:07:56] über so ein paar Technik-Themen

[1:07:58] oder auch rund um die Ausbildung.

[1:08:00] Ist ja alles möglich.

[1:08:02] Ja, schick doch einfach eine Mail,

[1:08:04] und wenn es sich anbietet,

[1:08:06] vielleicht können wir uns einfach mal unterhalten.

[1:08:08] Okay, dann würde ich sagen,

[1:08:10] falls dich die Informationen von Matthias noch interessieren,

[1:08:12] die er genannt hat, die Links, das Video und so weiter,

[1:08:14] dann schau doch einfach mal in die Shownotes.

[1:08:16] Die sind wie immer zu finden unter

[1:08:18] www.anwendungs-entwickler-podcast.de

[1:08:20] für die heutige 128. Episode.

[1:08:22] Keine Angst,

[1:08:24] du musst nicht die 1 und 7 Nullen eingeben,

[1:08:26] sondern 1, 2, 8, das reicht.

[1:08:28] Und wenn du noch Fragen hast

[1:08:30] oder Anregungen rund ums Testen

[1:08:32] oder um irgendwelche anderen Themen,

[1:08:34] dann schreib uns doch gerne auch einen Kommentar unter die Episode.

[1:08:36] Du hast ja gehört, Matthias ist nicht so

[1:08:38] im Netz direkt zu erreichen.

[1:08:40] Das heißt, wenn du noch irgendwie was von ihm wissen willst

[1:08:42] oder auch von mir, ja,

[1:08:44] hau uns einfach einen Kommentar in die Shownotes,

[1:08:46] und wir würden uns auf jeden Fall über Feedback

[1:08:48] und Anregungen freuen.

[1:08:50] Und ja, damit mache ich für heute auch Schluss.

[1:08:52] Ich sage vielen Dank fürs Zuhören

[1:08:54] und bis zum nächsten Mal.

[1:08:56] Tschüss!

Polyglot Clean Code Developer
About the Author
Ausbildungsleiter für Fachinformatiker:innen Anwendungsentwicklung, IHK-Prüfer und ehemaliger Hochschuldozent für Programmierung und Software-Engineering.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert