Integrationstest mit einer lokalen DynamoDB-Instanz

1. Überblick

Wenn wir eine Anwendung entwickeln, die Amazon DynamoDB verwendet, kann es schwierig sein, Integrationstests ohne lokale Instanz zu entwickeln.

In diesem Lernprogramm werden verschiedene Möglichkeiten zum Konfigurieren, Starten und Stoppen einer lokalen DynamoDB für unsere Integrationstests beschrieben.

Dieses Tutorial ergänzt auch unseren bestehenden Link:/spring-data-dynamodb[DynamoDB-Artikel].

2. Aufbau

2.1. Maven-Setup

DynamoDB Local ist ein von Amazon entwickeltes Tool, das alle DynamoDB-APIs unterstützt. Sie können die tatsächlichen DynamoDB-Tabellen in der Produktion nicht direkt bearbeiten, sondern lokal ausführen.

Zunächst fügen wir die DynamoDB Local-Abhängigkeit zur Liste der Abhängigkeiten in unserer Maven-Konfiguration hinzu:

<dependency>
    <groupId>com.amazonaws</groupId>
    <artifactId>DynamoDBLocal</artifactId>
    <version>1.11.86</version>
    <scope>test</scope>
</dependency>

Als Nächstes müssen wir das Amazon DynamoDB-Repository hinzufügen, da die Abhängigkeit im Maven Central-Repository nicht vorhanden ist.

Wir können den nächstgelegenen Amazon-Server unserer aktuellen IP-Adresse auswählen

<repository>
    <id>dynamodb-local</id>
    <name>DynamoDB Local Release Repository</name>
    <url>https://s3-us-west-2.amazonaws.com/dynamodb-local/release</url>
</repository>

2.2. SQLite4Java-Abhängigkeit hinzufügen

DynamoDB Local verwendet intern die Bibliothek SQLite4Java . Daher müssen wir auch die Bibliotheksdateien einschließen, wenn wir den Test ausführen. Die SQLite4Java-Bibliotheksdateien hängen von der Umgebung ab, in der der Test ausgeführt wird. Maven kann sie jedoch nacheinander abrufen, sobald wir die DynamoDBLocal-Abhängigkeit deklarieren.

Als Nächstes müssen Sie einen neuen Erstellungsschritt hinzufügen, um native Bibliotheken in einen bestimmten Ordner zu kopieren, den wir später in der JVM-Systemeigenschaft definieren.

Lassen Sie uns die aus dem SQLite4Java-Archiv geladenen Dateien in einen Ordner namens native-libs kopieren:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-dependency-plugin</artifactId>
    <version>2.10</version>
    <executions>
        <execution>
            <id>copy</id>
            <phase>test-compile</phase>
            <goals>
                <goal>copy-dependencies</goal>
            </goals>
            <configuration>
                <includeScope>test</includeScope>
                <includeTypes>so,dll,dylib</includeTypes>
                <outputDirectory>${project.basedir}/native-libs</outputDirectory>
            </configuration>
        </execution>
    </executions>
</plugin>

** 2.3. Legen Sie die SQLite4Java-Systemeigenschaft + fest

**

Jetzt referenzieren wir den zuvor erstellten Ordner (wo sich die SQLite4Java-Bibliotheken befinden) und verwenden eine JVM-Systemeigenschaft namens sqlite4java.library.path :

System.setProperty("sqlite4java.library.path", "native-libs");

Um den Test später erfolgreich ausführen zu können, müssen alle SQLite4Java-Bibliotheken in dem Ordner vorhanden sein, der von der Systemeigenschaft sqlite4java.library.path definiert wird. Wir müssen Maven test-compile ( mvn test-compile ) mindestens einmal ausführen, um die Voraussetzung zu erfüllen.

** 3. Einrichten des Lebenszyklus der Testdatenbank __

__ **

Wir können den Code zum Erstellen und Starten des lokalen DynamoDB-Servers in einer Setup-Methode definieren, die mit @ BeforeClass; versehen ist, und den Server symmetrisch in einer mit @ AfterClass annotierten Abreißmethode stoppen.

Im folgenden Beispiel starten wir den lokalen DynamoDB-Server an Port 8000 und stellen sicher, dass er nach dem Ausführen unserer Tests erneut angehalten wurde:

public class ProductInfoDAOIntegrationTest {
    private static DynamoDBProxyServer server;

    @BeforeClass
    public static void setupClass() throws Exception {
        System.setProperty("sqlite4java.library.path", "native-libs");
        String port = "8000";
        server = ServerRunner.createServerFromCommandLineArgs(
          new String[]{"-inMemory", "-port", port});
        server.start();
       //...
    }

    @AfterClass
    public static void teardownClass() throws Exception {
        server.stop();
    }

   //...
}

Wir können den lokalen DynamoDB-Server auch mit java.net.ServerSocket anstelle eines festen Ports an jedem verfügbaren Port ausführen. In diesem Fall müssen wir den Test auch so konfigurieren, dass der Endpunkt auf den richtigen DynamoDB-Port gesetzt wird.

public String getAvailablePort() throws IOException {
    ServerSocket serverSocket = new ServerSocket(0);
    return String.valueOf(serverSocket.getLocalPort());
}

4. Alternativer Ansatz: Verwenden von @ ClassRule

Wir können die vorherige Logik in eine JUnit-Regel einschließen, die dieselbe Aktion ausführt:

public class LocalDbCreationRule extends ExternalResource {
    private DynamoDBProxyServer server;

    public LocalDbCreationRule() {
        System.setProperty("sqlite4java.library.path", "native-libs");
    }

    @Override
    protected void before() throws Exception {
        String port = "8000";
        server = ServerRunner.createServerFromCommandLineArgs(
          new String[]{"-inMemory", "-port", port});
        server.start();
    }

    @Override
    protected void after() {
        this.stopUnchecked(server);
    }

    protected void stopUnchecked(DynamoDBProxyServer dynamoDbServer) {
        try {
            dynamoDbServer.stop();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}

Um unsere benutzerdefinierte Regel verwenden zu können, müssen Sie eine Instanz mit @ ClassRule erstellen und kommentieren (siehe unten). Der Test erstellt und startet den lokalen DynamoDB-Server erneut vor der Initialisierung der Testklasse.

Beachten Sie, dass der Zugriffsmodifizierer der Testregel public sein muss, um den Test auszuführen:

public class ProductInfoRepositoryIntegrationTest {
    @ClassRule
    public static LocalDbCreationRule dynamoDB = new LocalDbCreationRule();

   //...
}

Eine kurze Anmerkung vor dem Abschluss: Da DynamoDB Local die SQLite-Datenbank intern verwendet, spiegelt die Leistung nicht die tatsächliche Leistung in der Produktion wider.

5. Fazit

In diesem Artikel haben wir gesehen, wie Sie DynamoDB Local für die Ausführung von Integrationstests einrichten und konfigurieren.

Wie immer finden Sie den Quellcode und das Konfigurationsbeispiel über Github .