Перейти к основному содержимому

Интеграционное тестирование с локальным экземпляром DynamoDB

· 4 мин. чтения

1. Обзор

Если мы разрабатываем приложение, которое использует DynamoDB от Amazon , может быть сложно разработать интеграционные тесты без локального экземпляра.

В этом руководстве мы рассмотрим несколько способов настройки, запуска и остановки локальной DynamoDB для наших интеграционных тестов .

Этот туториал также дополняет нашу существующую статью о DynamoDB .

2. Конфигурация

2.1. Настройка Maven

DynamoDB Local — это инструмент, разработанный Amazon, который поддерживает все API DynamoDB. Он не манипулирует напрямую реальными таблицами DynamoDB в производственной среде, а вместо этого выполняет это локально.

Во-первых, мы добавляем зависимость DynamoDB Local в список зависимостей в нашей конфигурации Maven:

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

Далее нам также нужно добавить репозиторий Amazon DynamoDB, поскольку в репозитории Maven Central нет зависимости.

Мы можем выбрать ближайший сервер Amazon к нашей текущей геолокации IP-адреса:

<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

DynamoDB Local использует библиотеку SQLite4Java внутри; таким образом, нам также необходимо включить файлы библиотеки при запуске теста. Файлы библиотеки SQLite4Java зависят от среды, в которой выполняется тест, но Maven может получить их транзитивно, как только мы объявим зависимость DynamoDBLocal.

Затем нам нужно добавить новый шаг сборки для копирования собственных библиотек в определенную папку, которую мы позже определим в системном свойстве JVM.

Давайте скопируем транзитивно извлеченные файлы библиотеки SQLite4Java в папку с именем 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. Установите системное свойство SQLite4Java

Теперь мы будем ссылаться на ранее созданную папку (где расположены библиотеки SQLite4Java), используя системное свойство JVM с именем sqlite4java.library.path :

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

Чтобы успешно запустить тест позже, необходимо, чтобы все библиотеки SQLite4Java находились в папке, определенной системным свойством sqlite4java.library.path . Мы должны запустить тестовую компиляцию Maven ( mvn test-compile ) хотя бы один раз , чтобы выполнить предварительное условие.

3. Настройка жизненного цикла тестовой базы данных ``

Мы можем определить код для создания и запуска локального сервера DynamoDB в методе установки, аннотированном @BeforeClass; и, симметрично, остановить сервер с помощью метода разрыва, аннотированного @AfterClass .

В следующем примере мы запустим локальный сервер DynamoDB на порту 8000 и убедимся, что он снова остановлен после выполнения наших тестов:

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

//...
}

Мы также можем запустить локальный сервер DynamoDB на любом доступном порту вместо фиксированного порта, используя java.net.ServerSocket . В этом случае мы также должны настроить тест, чтобы установить конечную точку на правильный порт DynamoDB :

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

4. Альтернативный подход: использование @ClassRule

Мы можем обернуть предыдущую логику в правило JUnit, которое выполняет то же действие:

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

Чтобы использовать наше пользовательское правило, нам нужно создать и аннотировать экземпляр с помощью @ClassRule , как показано ниже. Опять же, тест создаст и запустит локальный сервер DynamoDB до инициализации тестового класса.

Обратите внимание, что модификатор доступа правила тестирования должен быть общедоступным , чтобы запустить тест:

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

//...
}

Прежде чем завершить, очень краткое замечание: поскольку DynamoDB Local использует базу данных SQLite для внутреннего использования, ее производительность не отражает реальную производительность в производственной среде.

5. Вывод

В этой статье мы увидели, как установить и настроить DynamoDB Local для запуска интеграционных тестов.

Как всегда, исходный код и пример конфигурации можно найти на Github .