Встроенный MongoDB при запуске интеграционных тестов

Мой вопрос является вариацией этого.

Поскольку моему проекту Java-веб-приложения требуется много фильтров / запросов на чтение и интерфейсов с такими инструментами, как GridFS, я изо всех сил пытаюсь придумать разумный способ использования MongoDB так, как предлагает вышеупомянутое решение.

Поэтому я рассматриваю возможность запуска встроенного экземпляра MongoDB вместе с моими интеграционными тестами. Я бы хотел, чтобы он запускался автоматически (для каждого теста или всего пакета), очищал базу данных для каждого теста и завершал работу в конце. Эти тесты могут выполняться на машинах разработки, а также на сервере CI, поэтому мое решение также должно быть переносимым.

Может ли кто-нибудь с большим знанием MongoDB помочь мне понять целесообразность такого подхода и / или, возможно, предложить какой-либо материал для чтения, который мог бы помочь мне начать?

Я также открыт для других предложений людей о том, как я могу подойти к этой проблеме...

16 ответов

Решение

Я нашел встроенную библиотеку MongoDB, которая выглядит довольно многообещающе и делает то, что вы просили.

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

Вот краткий пример использования, который я только что попробовал, и он отлично работает:

public class EmbeddedMongoTest {
    private static final String DATABASE_NAME = "embedded";

    private MongodExecutable mongodExe;
    private MongodProcess mongod;
    private Mongo mongo;

    @Before
    public void beforeEach() throws Exception {
        MongoDBRuntime runtime = MongoDBRuntime.getDefaultInstance();
        mongodExe = runtime.prepare(new MongodConfig(Version.V2_3_0, 12345, Network.localhostIsIPv6()));
        mongod = mongodExe.start();
        mongo = new Mongo("localhost", 12345);
    }

    @After
    public void afterEach() throws Exception {
        if (this.mongod != null) {
            this.mongod.stop();
            this.mongodExe.stop();
        }
    }

    @Test
    public void shouldCreateNewObjectInEmbeddedMongoDb() {
        // given
        DB db = mongo.getDB(DATABASE_NAME);
        DBCollection col = db.createCollection("testCollection", new BasicDBObject());

        // when
        col.save(new BasicDBObject("testDoc", new Date()));

        // then
        assertThat(col.getCount(), Matchers.is(1L));
    }
}

Вот обновленная (для 2019 года) версия принятого ответа от @rozky (многое изменилось в библиотеках Mongo и Embedded MongoDB).

package com.example.mongo;

import com.mongodb.BasicDBObject;
import com.mongodb.MongoClient;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import de.flapdoodle.embed.mongo.MongodExecutable;
import de.flapdoodle.embed.mongo.MongodProcess;
import de.flapdoodle.embed.mongo.MongodStarter;
import de.flapdoodle.embed.mongo.config.IMongodConfig;
import de.flapdoodle.embed.mongo.config.MongodConfigBuilder;
import de.flapdoodle.embed.mongo.config.Net;
import de.flapdoodle.embed.mongo.distribution.Version;
import de.flapdoodle.embed.process.runtime.Network;
import java.util.Date;
import org.junit.After;
import static org.junit.Assert.*;
import org.junit.Before;
import org.junit.Test;

public class EmbeddedMongoTest
{
    private static final String DATABASE_NAME = "embedded";

    private MongodExecutable mongodExe;
    private MongodProcess mongod;
    private MongoClient mongo;

    @Before
    public void beforeEach() throws Exception {
        MongodStarter starter = MongodStarter.getDefaultInstance();
        String bindIp = "localhost";
        int port = 12345;
        IMongodConfig mongodConfig = new MongodConfigBuilder()
        .version(Version.Main.PRODUCTION)
        .net(new Net(bindIp, port, Network.localhostIsIPv6()))
        .build();
        this.mongodExe = starter.prepare(mongodConfig);
        this.mongod = mongodExe.start();
        this.mongo = new MongoClient(bindIp, port);
    }

    @After
    public void afterEach() throws Exception {
        if (this.mongod != null) {
            this.mongod.stop();
            this.mongodExe.stop();
        }
    }

    @Test
    public void shouldCreateNewObjectInEmbeddedMongoDb() {
        // given
        MongoDatabase db = mongo.getDatabase(DATABASE_NAME);
        db.createCollection("testCollection");
        MongoCollection<BasicDBObject> col = db.getCollection("testCollection", BasicDBObject.class);

        // when
        col.insertOne(new BasicDBObject("testDoc", new Date()));

        // then
        assertEquals(1L, col.countDocuments());
    }

}

Существует продукт Foursquare Fongo. Фонго - это Java-реализация Монго в памяти. Он перехватывает вызовы стандартного драйвера mongo-java для поиска, обновления, вставки, удаления и других методов. Основное использование - для легкого модульного тестирования, когда вы не хотите ускорять процесс монго.

Если вы используете Maven, вас может заинтересовать плагин, который я создал, который оборачивает API-интерфейс flapdoodle.de 'embedded mongo':

embedmongo-Maven-плагин

Это обеспечивает start цель, которую вы можете использовать, чтобы запустить любую версию MongoDB, которую вы хотите (например, во время pre-integration-test) и stop цель, которая остановит MongoDB (например, во время post-integration-test).

Реальное преимущество использования этого плагина перед другими заключается в том, что нет необходимости предварительно устанавливать MongoDB. Бинарные файлы MongoDB загружаются и хранятся в ~/.embedmongo для будущих сборок.

Если вы используете sbt и specs2, я написал такую ​​же оболочку для embedmongo

https://github.com/athieriot/specs2-embedmongo

С весенней загрузкой 1.3 вы можете использовать EmbeddedMongoAutoConfiguration

pom.xml

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.3.2.RELEASE</version>
</parent>
 ...
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-mongodb</artifactId>
    </dependency>
    <dependency>
        <groupId>de.flapdoodle.embed</groupId>
        <artifactId>de.flapdoodle.embed.mongo</artifactId>
        <version>${embedded-mongo.version}</version>
    </dependency>

MongoConfig

@Configuration
@EnableAutoConfiguration(exclude = { EmbeddedMongoAutoConfiguration.class })
public class MongoConfig{
}

Вы можете запустить MongoDB в памяти начиная с версии 3.2.6. С сайта:

Начиная с MongoDB Enterprise версии 3.2.6, механизм хранения в памяти является частью общей доступности (GA) в 64-разрядных сборках. Помимо некоторых метаданных и диагностических данных, механизм хранения в памяти не поддерживает никаких данных на диске, включая данные конфигурации, индексы, учетные данные пользователя и т. Д.

Если вы используете Maven, вы можете использовать наш http://mvnrepository.com/artifact/com.wenzani/mongodb-maven-plugin

Не только для модульных тестов, но и для чтения этого поста в блоге, если вы хотите использовать MongoDB (даже кластер) в качестве развертывания в памяти, если вы используете Linux.

http://edgystuff.tumblr.com/post/49304254688

Было бы здорово иметь его из коробки, как RavenDB, хотя.

Не только для модульного тестирования, но также объяснил, как использовать inmemory mongodb с rest api.

зависимость maven:

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

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

================================================== ===========================

application.properties

server.port = 8080
spring.data.mongodb.database=user_db
spring.data.mongodb.port=27017
spring.data.mongodb.host=localhost

================================================== ===========================

UserRepository.java

открытый интерфейс UserRepository расширяет MongoRepository{

}

для справки и всего кода Java используйте ссылку ниже:(пошаговое объяснение)

https://www.youtube.com/watch?v=2Tq2Q7EzhSA&t=7s

Вы также можете проверить этот проект, который имитирует MongoDB в памяти JVM. https://github.com/thiloplanz/jmockmongo Но он все еще находится в разработке.

Подобно плагину embedmongo-maven-plugin, упомянутому здесь, существует также плагин Gradle Mongo.

Как и плагин Maven, он также оборачивает API-интерфейс flapdoodle EmbeddedMongoDb и позволяет запускать управляемый экземпляр Mongo из ваших сборок Gradle.

Спектакли лучше при исполнении mongod с участием storageEngine='ephemeralForTest'

new MongodConfigBuilder()
    .version(Version.Main.PRODUCTION)
    .cmdOptions(new MongoCmdOptionsBuilder()
         .useStorageEngine("ephemeralForTest")
         .build())
    .net(new Net("localhost", port, Network.localhostIsIPv6()))
    .build()

Проверьте этот пример кода здесь: https://github.com/familysyan/embedded-mongo-integ. Нет установки, нет зависимости. Это просто независимый от платформы ant-скрипт, который делает загрузку и настройку для вас. Это также убирает все после ваших тестов.

Для запуска Embedded mongodb для интеграционного теста необходимы следующие зависимости maven:

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

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-autoconfigure</artifactId>
            <version>2.5.2</version>
        </dependency>

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

Попробуйте использовать приведенный ниже код, вырезанный для EmbeddedMongoAutoConfiguration:

      import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.mongo.MongoProperties;
import org.springframework.boot.autoconfigure.mongo.embedded.EmbeddedMongoAutoConfiguration;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;

@SpringBootApplication
public class EmbeddedMongoApplication {

    public static void main(String[] args) {
         System.setProperty("os.arch", "x86_64");
         SpringApplication.run(EmbeddedMongoApplication.class, args);
    }
    
    @Bean
    public EmbeddedMongoAutoConfiguration embeddedMongoAutoConfiguration(MongoProperties mongoProperties) {
        return new EmbeddedMongoAutoConfiguration(mongoProperties);
    }
}

Примечание:

Встроенный mongodb будет загружен по указанному ниже пути. Так что примите во внимание, что у этого пути есть надлежащее разрешение.

      Linux : $HOME/.embedmongo/linux/mongodb-linux-x86_64-3.2.2.tgz
Windows : C:\Users\<username>\.embedmongo\win32\mongodb-win32-x86_64-3.x.x.zip

В производстве вы будете использовать реальную базу данных.

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

Ложная реализация может вести себя не так, как настоящая. При тестировании вы должны стремиться к правильности. Скорость исполнения занимает второе место.

Другие вопросы по тегам