In meinen Kotlin JUnit-Tests möchte ich eingebettete Server starten / stoppen und sie in meinen Tests verwenden.
Ich habe versucht, die JUnit- @Before
Annotation für eine Methode in meiner Testklasse zu verwenden, und sie funktioniert einwandfrei, ist jedoch nicht das richtige Verhalten, da jeder Testfall statt nur einmal ausgeführt wird.
Daher möchte ich die @BeforeClass
Annotation für eine Methode verwenden, aber das Hinzufügen zu einer Methode führt zu einem Fehler, der besagt, dass es sich um eine statische Methode handeln muss. Kotlin scheint keine statischen Methoden zu haben. Gleiches gilt für statische Variablen, da ich für die Verwendung in den Testfällen einen Verweis auf den eingebetteten Server behalten muss.
Wie erstelle ich diese eingebettete Datenbank nur einmal für alle meine Testfälle?
class MyTest {
@Before fun setup() {
// works in that it opens the database connection, but is wrong
// since this is per test case instead of being shared for all
}
@BeforeClass fun setupClass() {
// what I want to do instead, but results in error because
// this isn't a static method, and static keyword doesn't exist
}
var referenceToServer: ServerType // wrong because is not static either
...
}
Hinweis: Diese Frage wurde absichtlich vom Autor geschrieben und beantwortet ( Selbst beantwortete Fragen ), sodass die Antworten auf häufig gestellte Kotlin-Themen in SO vorhanden sind.
quelle
Antworten:
Ihre Unit-Test-Klasse benötigt normalerweise einige Dinge, um eine gemeinsam genutzte Ressource für eine Gruppe von Testmethoden zu verwalten. Und in Kotlin können Sie
@BeforeClass
und@AfterClass
nicht in der Testklasse, sondern innerhalb des Begleitobjekts zusammen mit der@JvmStatic
Annotation verwenden .Die Struktur einer Testklasse würde folgendermaßen aussehen:
Vor diesem Hintergrund sollten Sie Folgendes lesen:
@JvmStatic
- Eine Annotation, die eine Companion-Objektmethode in eine statische Methode für die äußere Klasse für Java Interop umwandeltlateinit
- Ermöglichtvar
die spätere Initialisierung einer Eigenschaft, wenn Sie einen genau definierten Lebenszyklus habenDelegates.notNull()
- kann anstellelateinit
einer Eigenschaft verwendet werden, die vor dem Lesen mindestens einmal festgelegt werden sollte.Hier finden Sie ausführlichere Beispiele für Testklassen für Kotlin, die eingebettete Ressourcen verwalten.
Der erste wird aus Solr-Undertow-Tests kopiert und geändert. Bevor die Testfälle ausgeführt werden, wird ein Solr-Undertow-Server konfiguriert und gestartet. Nach dem Ausführen der Tests werden alle durch die Tests erstellten temporären Dateien bereinigt. Außerdem wird sichergestellt, dass Umgebungsvariablen und Systemeigenschaften korrekt sind, bevor die Tests ausgeführt werden. Zwischen den Testfällen werden alle temporär geladenen Solr-Kerne entladen. Der Test:
Und ein weiterer Start von AWS DynamoDB local als eingebettete Datenbank (kopiert und leicht geändert von Running AWS DynamoDB-local embedded ). Dieser Test muss das hacken,
java.library.path
bevor etwas anderes passiert, sonst wird die lokale DynamoDB (mit SQLite mit Binärbibliotheken) nicht ausgeführt. Anschließend wird ein Server gestartet, der für alle Testklassen freigegeben wird, und temporäre Daten zwischen den Tests werden bereinigt. Der Test:HINWEIS: Einige Teile der Beispiele sind mit abgekürzt
...
quelle
Das Verwalten von Ressourcen mit Vorher / Nachher-Rückrufen in Tests hat natürlich folgende Vorteile:
Es hat auch einige Nachteile. Eine wichtige davon ist, dass sie den Code verschmutzt und den Code gegen das Prinzip der Einzelverantwortung verstößt. Tests testen jetzt nicht nur etwas, sondern führen auch eine Schwergewichtsinitialisierung und Ressourcenverwaltung durch. In einigen Fällen kann dies in Ordnung sein (z. B. beim Konfigurieren eines
ObjectMapper
), aber das Ändernjava.library.path
oder Laichen anderer Prozesse (oder eingebetteter In-Process-Datenbanken) ist nicht so unschuldig.Warum nicht diese Dienste als Abhängigkeiten für den Test , die für „injection“ behandeln, wie beschrieben durch 12factor.net .
Auf diese Weise starten und initialisieren Sie Abhängigkeitsdienste außerhalb des Testcodes.
Heutzutage sind Virtualisierung und Container fast überall und die meisten Entwicklermaschinen können Docker ausführen. Und die meisten Anwendungen haben eine Docker-Version: Elasticsearch , DynamoDB , PostgreSQL und so weiter. Docker ist eine perfekte Lösung für externe Services, die Ihre Tests benötigen.
dependsOn
undfinalizedBy
DSL-Funktion zum Definieren von Abhängigkeiten). Eine Aufgabe kann natürlich dasselbe Skript ausführen, das der Entwickler manuell mithilfe von Shell-Outs / Prozess-Execs ausführt.Dieser Ansatz:
Natürlich hat es seine Mängel (im Grunde die Aussagen, von denen ich ausgegangen bin):
quelle