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

Интеграционное тестирование Spring Boot со встроенной MongoDB

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

Задача: Медиана двух отсортированных массивов

Даны два отсортированных массива размерами n и m. Найдите медиану слияния этих двух массивов.
Временная сложность решения должна быть O(log(m + n)) ...

ANDROMEDA

1. Обзор

В этом руководстве мы узнаем, как использовать встроенное решение MongoDB от Flapdoodle вместе с Spring Boot для плавного запуска интеграционных тестов MongoDB.

MongoDB — популярная база данных документов NoSQL . Благодаря высокой масштабируемости, встроенному сегментированию и отличной поддержке сообщества многие разработчики часто называют его «хранилищем NoSQL» .

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

2. Зависимости Maven

Во-первых, давайте настроим родительский Maven для нашего проекта Boot.

Благодаря родителю нам не нужно вручную определять версию для каждой зависимости Maven .

Естественно, мы будем использовать Spring Boot:

<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.6.1</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>

Вы можете найти последнюю версию Boot здесь .

Поскольку мы добавили родителя Spring Boot, мы можем добавить необходимые зависимости, не указывая их версии:

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>

spring-boot-starter-data-mongodb включит поддержку Spring для MongoDB:

<dependency>
<groupId>de.flapdoodle.embed</groupId>
<artifactId>de.flapdoodle.embed.mongo</artifactId>
<scope>test</scope>
</dependency>

de.flapdoodle.embed.mongo предоставляет встроенную базу данных MongoDB для интеграционных тестов.

3. Протестируйте с помощью встроенной MongoDB

В этом разделе рассматриваются два сценария: тест Spring Boot и ручной тест.

3.1. Весенний загрузочный тест

После добавления зависимости de.flapdoodle.embed.mongo Spring Boot автоматически попытается загрузить и запустить встроенную MongoDB при выполнении тестов.

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

На этом этапе мы должны запустить и пройти образец интеграционного теста JUnit 5:

@DataMongoTest
@ExtendWith(SpringExtension.class)
public class MongoDbSpringIntegrationTest {
@DisplayName("given object to save"
+ " when save object using MongoDB template"
+ " then object is saved")
@Test
public void test(@Autowired MongoTemplate mongoTemplate) {
// given
DBObject objectToSave = BasicDBObjectBuilder.start()
.add("key", "value")
.get();

// when
mongoTemplate.save(objectToSave, "collection");

// then
assertThat(mongoTemplate.findAll(DBObject.class, "collection")).extracting("key")
.containsOnly("value");
}
}

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

...Starting MongodbExampleApplicationTests on arroyo with PID 10413...

3.2. Проверка конфигурации вручную

Spring Boot автоматически запустит и настроит встроенную базу данных, а затем добавит экземпляр MongoTemplate для нас. Однако иногда нам может потребоваться настроить встроенную базу данных Mongo вручную (например, при тестировании конкретной версии БД).

В следующем фрагменте показано, как мы можем настроить встроенный экземпляр MongoDB вручную. Это примерно эквивалентно предыдущему тесту Spring:

class ManualEmbeddedMongoDbIntegrationTest {
private static final String CONNECTION_STRING = "mongodb://%s:%d";

private MongodExecutable mongodExecutable;
private MongoTemplate mongoTemplate;

@AfterEach
void clean() {
mongodExecutable.stop();
}

@BeforeEach
void setup() throws Exception {
String ip = "localhost";
int port = 27017;

ImmutableMongodConfig mongodConfig = MongodConfig
.builder()
.version(Version.Main.PRODUCTION)
.net(new Net(ip, port, Network.localhostIsIPv6()))
.build();

MongodStarter starter = MongodStarter.getDefaultInstance();
mongodExecutable = starter.prepare(mongodConfig);
mongodExecutable.start();
mongoTemplate = new MongoTemplate(MongoClients.create(String.format(CONNECTION_STRING, ip, port)), "test");
}

@DisplayName("given object to save"
+ " when save object using MongoDB template"
+ " then object is saved")
@Test
void test() throws Exception {
// given
DBObject objectToSave = BasicDBObjectBuilder.start()
.add("key", "value")
.get();

// when
mongoTemplate.save(objectToSave, "collection");

// then
assertThat(mongoTemplate.findAll(DBObject.class, "collection")).extracting("key")
.containsOnly("value");
}
}

Обратите внимание, что мы можем быстро создать bean-компонент MongoTemplate , сконфигурированный для использования нашей настроенной вручную встроенной базы данных, и зарегистрировать его в контейнере Spring, просто создав, например, @TestConfiguration с методом @Bean , который вернет новый MongoTemplate(MongoClients.create(connectionString, " испытание») .

Больше примеров можно найти в официальном репозитории Flapdoodle на GitHub .

3.3. логирование

Мы можем настроить сообщения журнала для MongoDB при запуске интеграционных тестов, добавив эти два свойства в файл src/test/resources/application.propertes :

logging.level.org.springframework.boot.autoconfigure.mongo.embedded
logging.level.org.mongodb

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

logging.level.org.springframework.boot.autoconfigure.mongo.embedded=off
logging.level.org.mongodb=off

3.4. Использование реальной базы данных в производстве

Поскольку мы добавили зависимость de.flapdoodle.embed.mongo с помощью <scope>test</scope> , нет необходимости отключать встроенную базу данных при работе в рабочей среде . Все, что нам нужно сделать, это указать детали подключения к MongoDB (например, хост и порт), и все готово.

Чтобы использовать встроенную БД вне тестов, мы можем использовать профили Spring, которые будут регистрировать правильный MongoClient (встроенный или рабочий) в зависимости от активного профиля.

Нам также нужно изменить область действия производственной зависимости на <scope>runtime</scope> .

4. Споры о встроенном тестировании

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

  • Конфигурация сопоставления объекта<->документа
  • Пользовательские прослушиватели событий жизненного цикла сохраняемости (см . AbstractMongoEventListener )
  • Логика любого кода, работающего напрямую с персистентным слоем

К сожалению, использование встроенного сервера нельзя рассматривать как «полное интеграционное тестирование» . Встроенная MongoDB от Flapdoodle не является официальным продуктом MongoDB. Поэтому мы не можем быть уверены, что он ведет себя именно так, как в производственной среде.

Если мы хотим запускать коммуникационные тесты в среде, максимально приближенной к рабочей, лучшим решением будет использование контейнера среды, такого как Docker.

Чтобы узнать больше о Docker, прочитайте нашу предыдущую статью здесь .

5. Вывод

Spring Boot чрезвычайно упрощает запуск тестов, проверяющих правильность сопоставления документов и интеграции с базой данных. Добавив правильную зависимость Maven, мы сразу же можем использовать компоненты MongoDB в интеграционных тестах Spring Boot.

Нужно помнить, что встроенный сервер MongoDB нельзя считать заменой «настоящему» серверу .

Полный исходный код всех примеров доступен на GitHub .