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 .