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

99

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

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

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

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

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

Теги:
junit
integration-testing
embedded-database

13 ответов

94
Лучший ответ

Я нашел 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));
    }
}
  • 1
    Просто использовал эту библиотеку, и она отлично работала. JUnit тестировал API Mongo на Mac. Рекомендуемые.
  • 1
    +1 отличная находка! Когда я впервые начал использовать mongodb год назад, отсутствие программного способа тестирования базы данных было одним из недостатков. Мы справились с этим, имея тестовый экземпляр в каждой среде, настроенный через файл свойств Java, но, разумеется, для этого нужно было установить mongo в каждой среде. Похоже, это решит все это.
Показать ещё 5 комментариев
18

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

  • 1
    Случается ли, что Fongo перехватывает вызовы в сеть, например, localhost: 27017, чтобы он мог служить поддельным поддельным сервером для включения тестирования интеграции без изменений кода?
  • 0
    mongo-java-server - это поддельная реализация поддельного сервера, которую можно использовать для тестирования интеграции без изменений кода.
7

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

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

7

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

embedmongo-maven-plugin

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

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

4

с 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{
}
  • 1
    Можете ли вы объяснить, что на самом деле делает аннотация "@EnableAutoConfiguration (exclude = {EmbeddedMongoAutoConfiguration.class})"?
  • 0
    Причиной, скорее всего, является зависимость de.flapdoodle.embed.mongo, не помеченная для области тестирования. Чтобы не брать его и не запускать встроенные монго в настройках производственных приложений, необходимо исключение.
3

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

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

2

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

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

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

2

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

2

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

1

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

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

0

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

}
0

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

0

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

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

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

  • 6
    Я думаю, что вы пропустили мою цель. Я не искал поддельный экземпляр Mongo, я хотел настоящий экземпляр, но встроенный в мои тесты. Причина состояла в том, чтобы запустить MongoDB и перевести его в определенное состояние, не загрязняя существующую базу данных, выполнить серию операций, а затем проверить результат, не просматривая произвольные данные, не связанные с моим тестом. Насколько это возможно, при этом поддерживая контролируемую среду тестирования.
  • 0
    Извините, слово «симуляция» и все эти предложения «в памяти» заставили меня забыть значение слова «встроенный» в Java-земле. Рад слышать это.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню