Spring Boot Integration Testing со встроенным MongoDB

Тестирование интеграции с Spring Boot с помощью встроенного MongoDB

1. обзор

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

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

Как и в случае с любой другой технологией сохранения,it’s critical to be able to test database integration with the rest of our application easily. К счастью, Spring Boot позволяет нам легко писать подобные тесты.

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

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

Спасибо родителюwe don’t need to define version for each Maven dependency manually.

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


    org.springframework.boot
    spring-boot-starter-parent
    2.0.3.RELEASE
     

Вы можете найти последнюю версию загрузкиhere.

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


    org.springframework.boot
    spring-boot-starter-data-mongodb

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


    de.flapdoodle.embed
    de.flapdoodle.embed.mongo
    test

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

3. Тест с использованием встроенного MongoDB

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

3.1. Spring Boot Test

После добавленияde.flapdoodle.embed.mongo зависимостиSpring Boot will automatically try to download and start the embedded 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. Однакоsometimes we might need to configure embedded Mongo database manually (например, при тестировании конкретной версии БД).

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

class ManualEmbeddedMongoDbIntegrationTest {
    private MongodExecutable mongodExecutable;
    private MongoTemplate mongoTemplate;

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

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

        IMongodConfig mongodConfig = new MongodConfigBuilder().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(new MongoClient(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, который вернет new MongoTemplate(new MongoClient(bindIp, port), “test”).

Больше примеров можно найти на официальном сайте FlapdoodleGitHub repository.

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>there’s no need to disable embedded database when running on production. Все, что нам нужно сделать, это указать детали подключения MongoDB (например, хост и порт), и мы готовы к работе.

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

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

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

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

  • Объект <→ Конфигурация сопоставления документов

  • Пользовательские прослушиватели событий жизненного цикла сохраняемости (см.AbstractMongoEventListener)

  • Логика любого кода, работающего напрямую со слоем персистентности

К сожалению,using an embedded server cannot be considered as “full integration testing”. Встроенный MongoDB Flapdoodle не является официальным продуктом MongoDB. Поэтому мы не можем быть уверены, что он ведет себя точно так же, как в производственной среде.

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

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

5. Заключение

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

Нам нужно помнить, чтоembedded MongoDB server cannot be considered a replacement for a “real” server.

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