Test d’intégration avec une instance DynamoDB locale

1. Vue d’ensemble

Si nous développons une application qui utilise la DynamoDB d’Amazon, il peut être difficile de développer des tests d’intégration sans une instance locale.

Dans ce didacticiel, nous allons explorer plusieurs façons de configurer, de démarrer et d’arrêter un DynamoDB local pour nos tests d’intégration .

Ce tutoriel complète également notre lien existant:/spring-data-dynamodb[article de DynamoDB].

2. Configuration

2.1. Configuration Maven

DynamoDB Local est un outil développé par Amazon qui prend en charge toutes les API DynamoDB. Il ne manipule pas directement les tables DynamoDB en production, mais les exécute localement.

Tout d’abord, nous ajoutons la dépendance DynamoDB Local à la liste des dépendances de notre configuration Maven:

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

Ensuite, nous devons également ajouter le référentiel Amazon DynamoDB, car la dépendance n’existe pas dans le référentiel Maven Central.

Nous pouvons sélectionner le serveur Amazon le plus proche de notre géolocalisation d’adresses IP actuelle:

<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. Ajouter une dépendance SQLite4Java

DynamoDB Local utilise la bibliothèque SQLite4Java en interne; par conséquent, nous devons également inclure les fichiers de bibliothèque lorsque nous exécutons le test. Les fichiers de bibliothèque SQLite4Java dépendent de l’environnement dans lequel le test est exécuté, mais Maven peut les extraire de manière transitoire une fois que nous avons déclaré la dépendance DynamoDBLocal.

Ensuite, nous devons ajouter une nouvelle étape de construction pour copier les bibliothèques natives dans un dossier spécifique que nous définirons dans la propriété système JVM ultérieurement.

Copions les fichiers de la bibliothèque SQLite4Java tirés de manière transitoire dans un dossier nommé native-libs :

<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. Définir la propriété système SQLite4Java

**

Nous allons maintenant référencer le dossier précédemment créé (où se trouvent les bibliothèques SQLite4Java), en utilisant une propriété système JVM nommée sqlite4java.library.path :

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

Pour pouvoir exécuter le test ultérieurement, il est obligatoire d’avoir toutes les bibliothèques SQLite4Java dans le dossier défini par la propriété système sqlite4java.library.path . Nous devons exécuter Maven test-compile ( mvn test-compile ) au moins une fois pour remplir les conditions préalables.

** 3. Configuration du cycle de vie de la base de tests __

__ **

Nous pouvons définir le code permettant de créer et de démarrer le serveur DynamoDB local dans une méthode de configuration annotée avec @ BeforeClass; et, symétriquement, d’arrêter le serveur dans une méthode de démontage annotée avec @ AfterClass .

Dans l’exemple suivant, nous allons démarrer le serveur DynamoDB local sur le port 8000 et nous assurer qu’il est à nouveau arrêté après l’exécution de nos tests:

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();
    }

   //...
}

Nous pouvons également exécuter le serveur DynamoDB local sur n’importe quel port disponible au lieu d’un port fixe en utilisant java.net.ServerSocket . Dans ce cas, nous devons également configurer le test pour définir le noeud final sur le bon port DynamoDB :

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

4. Approche alternative: Utiliser @ ClassRule

Nous pouvons envelopper la logique précédente dans une règle JUnit qui effectue la même action:

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);
        }
    }
}

Pour utiliser notre règle personnalisée, nous devons créer et annoter une instance avec @ ClassRule comme indiqué ci-dessous. Là encore, le test créera et démarrera le serveur DynamoDB local avant l’initialisation de la classe de test.

Notez que le modificateur d’accès de la règle de test doit être public pour exécuter le test:

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

   //...
}

Avant de conclure, une remarque très rapide: puisque DynamoDB Local utilise la base de données SQLite en interne, ses performances ne reflètent pas les performances réelles en production.

5. Conclusion

Dans cet article, nous avons vu comment installer et configurer DynamoDB Local pour exécuter des tests d’intégration.

Comme toujours, le code source et l’exemple de configuration sont disponibles à l’adresse over sur Github .