Path: csiph.com!fu-berlin.de!uni-berlin.de!individual.net!not-for-mail From: "Christian H. Kuhn" Newsgroups: de.comp.lang.java Subject: =?UTF-8?Q?Mocking_von_Dateien_in_privaten_Methoden_m=c3=b6glich=3f?= Date: Fri, 1 Sep 2017 14:31:15 +0200 Lines: 131 Message-ID: Mime-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Trace: individual.net 07I+BsgvBcFdesn2Wg4SegYH3Onvg1piio18HBiNWd90GRzYI= Cancel-Lock: sha1:sjX7SVU9Wyl/ZAOFXY05s/YxUYc= X-Mozilla-News-Host: snews://news.individual.net:563 User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:52.0) Gecko/20100101 Thunderbird/52.3.0 Xref: csiph.com de.comp.lang.java:13124 Hallo Gemeinde, Ein Programm verwendet Input von Dateien im Filesystem, deren Name hardcoded ist. Die Originalfiles sind zu groß, um sie in Tests zu benutzen. Ich möchte Mocks für diese Dateien verwenden. _Zweck des Programms:_ Deutscher Schachbund (DSB) und Weltschachverband (FIDE) veröffentlichen Listen der Wertungszahlen ihrer Spieler. Der DSB vergibt nur eine Wertung (DWZ), die FIDE deren drei (ELO für Standard, Rapid und Blitz). Das Turniersystem „Schweizer System“ benutzt Wertungszahlen zum Erstellen einer Startrangliste. Das in Deutschland meistverwendete Programm „SwissChess“ ermöglicht die schnelle Übernahme von Wertungszahlen durch sog. Hintergrunddateien. Die bislang offiziell veröffentlichten Hintergrunddateien tragen dort nur DWZ und Standard-ELO ein. Für Rapid- und Blitzturniere wäre eine Hintergrunddatei wünschenswert, in der die Standard-ELO mit der Rapid- bzw. Blitz-ELO überschrieben ist, sofern existent. Solche Hintergrunddateien erzeugt mein Programm. Es funktioniert soweit. Bevor ich den Quellcode veröffentliche, möchte ich automatische Tests erstellen. _Struktur:_ Ein bash-Script lädt die Wertungsdateien von DSB und FIDE herunter, entpackt sie, ruft das JAVA-Programm auf, packt dessen Output und verschiebt ihn in ein Verzeichnis, das über den Webserver erreichbar ist, und räumt auf. Das Java-Programm arbeitet zweistufig: Im ersten Schritt werden die Wertungsdateien geparst und die Daten in eine Postgresql-Datenbank geschrieben. Im zweiten Schritt werden die gespeicherten Daten aus der Datenbank ausgelesen und in der richtigen Formatierung in die Ausgabedateien geschrieben. Für beide Schritte existiert je eine Klasse. Die Schnittstelle enthält nur je eine statische Funktion importData(Connection) bzw. exportData(Connection) mit scope package. Öffentliche Schnittstelle des package ist nur main() von QFdsbStarter. Dort wird die JDBC-Connection aus Daten aus einem Ini4j-File erzeugt und dann importData() und exportData() aufgerufen. _Problem:_ Die Originaldateien enthalten ca. 90k (DSB) bzw. 330k (FIDE) Spieler. Ein vollständiger Durchlauf dauert ca. 100 min. Zu Testzwecken wäre es wünschenswert, wenn statt der Originaldateien Testdateien mit einigen wenigen testrelevanten Datensätzen verwendet werden könnten. Natürlich ist es möglich, entsprechend vorbereitete Dateien anstelle der Originaldaten in den entsprechenden Ordner zu kopieren. Ich meine aber einmal gelernt zu haben, dass es nicht so wahnsinnig toll ist, wenn automatisierte Tests solche externen Abhängigkeiten haben. Besser wäre es, wenn stattdessen Mocks benutzt werden könnten. Die Dateien sind aber hardcoded und die Dateinamen, die erzeugten Paths und Reader innerhalb der zu testenden Klasse private bzw. lokal. Gibt es dennoch eine Möglichkeit, aus der Testklasse heraus Mocks zu erzeugen? Und hier noch die relevanten Auszüge aus dem Quellcode: package de.qno.fdsb; import [...] final class QFdsbImporter { private static final String ISO_8859_1 = "ISO-8859-1"; private QFdsbImporter() { // empty } static void importData(final Connection _connection) throws QFdsbException { clearTables(_connection); fillFideTables(_connection); fillDsbTables(_connection); } private static void clearTables(final Connection _connection) throws QFdsbException { [...] // some DELETE * FROM statements } /** * writes downloaded FIDE rating lists in database */ private static void fillFideTables(final Connection _connection) throws QFdsbException { [...] // similar do DSB } /** * Writes DSB rating list in database */ private static void fillDsbTables(final Connection _connection) throws QFdsbException { final LinkedList dsbFiles = new LinkedList(Arrays.asList("verbaende", "vereine", "spieler")); Path file; for (final String dsbFile : dsbFiles) { file = QFdsbStarter.home().resolve(dsbFile + ".csv"); try (PreparedStatement insertStatement = _connection .prepareStatement("INSERT INTO verbaende VALUES (?, ?, ?, ?);"); CSVReader reader = new CSVReaderBuilder(Files.newBufferedReader(file, Charset.forName(ISO_8859_1))) .withSkipLines(1).build()) { // _hier ist die entscheidende Stelle_ switch (dsbFile) { case "verbaende": writeDsbVerbaendeToTable(reader, insertStatement); break; case "vereine": writeDsbVereineToTable(reader, insertStatement); break; case "spieler": writeDsbSpielerToTable(reader, insertStatement); break; default: break; } } catch (SQLException e) { throw new QFdsbException( "Problems while writing verbaende data into DSB database or with insert statement for DSB " + dsbFile + " database", e); } catch (IOException e) { throw new QFdsbException("Problems while reading DSB " + dsbFile + " data file", e); } } } [...] } TIA QNo