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

Мой вопрос - это вариант этого.

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

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

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

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

Ответ 1

Здесь обновленная (для 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());
    }

}

Ответ 2

Я нашел Embedded 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));
    }
}

Ответ 3

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

Ответ 4

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

embedmongo-maven-plugin

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

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

Ответ 6

с spring -boot 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{
}

Ответ 7

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

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

Ответ 9

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

Ответ 10

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

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

Было бы здорово, если бы он был из коробки, как RavenDB.

Ответ 11

Как и в упомянутом здесь встраиваемом plugmongo-maven-плагине, есть также Gradle Монгонский плагин доступно.

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

Ответ 12

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

Ответ 13

Кажется, что ответ № 3 от @Collin Krawll основан на старой версии de.flapdoodle.embed.mongo. Я только что попробовал последнюю версию 2.2.0 с него, и IMongoConfig больше не разрешим.

Я что-то пропустил?

Ответ 14

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

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

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