統合テストの実行時に埋め込まれたMongoDB


112

私の質問はのバリエーションで、この1

私のJava Webアプリプロジェクトには、多くの読み取りフィルター/クエリと、GridFSなどのツールとのインターフェイスが必要であるため、上記のソリューションが示唆する方法でMongoDBを使用する賢明な方法を考えるのに苦労しています。

したがって、統合テストと一緒にMongoDBの埋め込みインスタンスを実行することを検討しています。自動的起動し(各テストまたはスイート全体)、すべてのテストでデータベースフラッシュし、最後にシャットダウンします。これらのテストは、CIサーバーだけでなく開発マシンでも実行される可能性があるため、私のソリューションもポータブルにする必要があります。

MongoDBの知識が豊富な人なら誰でも、このアプローチの実現可能性を理解するのに役立ちますか、あるいは私が始めるのに役立つ可能性のある読み物を提案できますか?

私はまた、この問題にどのように取り組むことができるかについて人々が持っているかもしれない他の提案を受け入れます...


あなたはMavenを使用している場合は、我々の使用することができますmvnrepository.com/artifact/com.wenzani/mongodb-maven-plugin
markdsievers

JVMメモリ内のMongoDBをシミュレートするこのプロジェクトを確認することもできます。github.com/thiloplanz/jmockmongoしかし、まだ開発中です。
Sebastien Lorber 2013年

単体テストではありませんが、Linuxを使用している場合、MongoDB(クラスターも含む)をインメモリデプロイメントとして実行する場合は、このブログ投稿をお読みください。edgystuff.tumblr.com/post/49304254688 RavenDBのようにそのまま使用できると便利です。
タミル

ここで説明したembedmongo-maven-pluginと同様に、Gradle Mongoプラグインも利用できます。Mavenプラグインと同様に、flapdoodle EmbeddedMongoDb apiもラップし、GradleビルドからMongoのマネージドインスタンスを実行できるようにします。
Robert Taylor

このコード例をここで確認してください:github.com/familysyan/embedded-mongo-integ。インストールなし、依存関係なし。これは、プラットフォームに依存しないantスクリプトであり、ダウンロードとセットアップを行います。また、テスト後にすべてをクリーンアップします。
エドモンド2017年

回答:


9

@rozkyから承認された回答の更新された(2019年の)バージョンです(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());
    }

}

1
各テストでEmbedded mongoを繰り返し開始および停止すると、ほとんどのテストが失敗します。すべてのテストの前に開始し、すべてのテストが実行されたらシャットダウンする方が良い
DBS

@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS)上記の変更に加えて、
DBS

@DBSランダムポートを使用して、新しい組み込みのmongoインスタンスでテストを同時に実行できるようにすることもできます。こちらのドキュメントをご覧ください
Collin Krawll

95

Embedded MongoDBを見つけました非常に有望に見え、あなたが要求したことを実行するライブラリを。

現在、MongoDBのバージョンをサポートしています1.6.53.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
このライブラリを使用しただけで、MacでMongo APIをテストするJUnitが完全に機能しました。オススメです。
Martin Dow

1
+1素晴らしい発見!1年前に初めてmongodbを使い始めたとき、データベースに対してプログラムでテストする方法がないことはマイナス面の1つでした。すべての環境でテストインスタンスを作成し、Javaプロパティファイルで設定しましたが、もちろん、すべての環境にmongoをインストールする必要がありました。これですべて解決できるようです。
andyb

いいね!回答が正確でなくなったため、回答を削除しました。誰もがこれがどれほど成熟しているのか考えていますか?非常に低いレベルでMongoDBをシミュレートする必要があると、かなり複雑になり、ソースから見るとかなり高いレベルに見えると想像できます。
Remon van Vliet、2012年

最後に、これを私のプロジェクトで試してみると、セットアップと実行が非常に簡単だったと報告できます。低レベルの呼び出しはすべて公式のcom.mongodb Java APIの一部であるため、通常のAPIを使用するよりも複雑ではありません。
andyb

17
このソリューションには注意してください。現在のオペレーティングシステムに関する情報を収集し、適切なプラットフォーム固有のMongoDBバイナリをインターネットからダウンロードして、デーモンを実行し、その他の構成を行います。エンタープライズソリューションとして、これはそうではありません。モックが唯一の現実的な選択肢かもしれません。
James Watkins、2013

18

フォースクエア製品のFongoがあります。Fongoは、mongoのインメモリJava実装です。検索、更新、挿入、削除、その他のメソッドのために、標準のmongo-java-driverへの呼び出しをインターセプトします。主な用途は、mongoプロセスを起動したくない軽量ユニットテストです。


1
Fongoは、たとえばlocalhost:27017へのネットワークへの呼び出しを傍受して、コードを変更せずに統合テストを可能にするドロップインの偽のサーバーとして機能できるようにしますか?

mongo-java-serverは、コードを変更せずに統合テストに使用できるドロップインの偽のサーバー実装です。
Benedikt Waldvogel 2018年

7

Mavenを使用している場合は、flapoodle.de 'embedded mongo' APIをラップする私が作成したプラグインに興味があるかもしれません。

embedmongo-maven-plugin

これは、start任意のバージョンのMongoDBを開始するために使用できる目標(例:中にpre-integration-test)と、stopMongoDBを停止する目標(例:中に)を提供します。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})"アノテーションが実際に何をしているのか説明できますか?
BrunoNegrãoZica

その理由はおそらく、de.flapdoodle.embed.mongo依存関係がテストスコープとしてマークされていないためです。それをピックアップして本番アプリケーションのセットアップで埋め込まれたmongoを実行しないようにするには、除外が必要です。
Sergey Shcherbakov、

3

バージョン3.2.6以降、MongoDBはメモリ内で実行できます。サイトから:

MongoDB Enterpriseバージョン3.2.6以降、インメモリストレージエンジンは64ビットビルドの一般提供(GA)の一部です。一部のメタデータと診断データを除いて、インメモリストレージエンジンは、構成データ、インデックス、ユーザー資格情報などのディスク上のデータを維持しません。


1

単体テストだけでなく、インメモリ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


0

で実行するmongodとパフォーマンスが向上しますstorageEngine='ephemeralForTest'

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

-1

本番環境では、実際のデータベースを使用します。

テストに製品の本番環境での動作を反映させる場合は、Mongoの実際のインスタンスを使用します。

偽の実装は、実際の実装とまったく同じように動作しない場合があります。テストするときは、正確さを追求する必要があります。実行速度は2番目です。


6
あなたは私の目的を逃したと思います。私はMongoの偽のインスタンスを探していませんでした。実際のインスタンスが必要でしたが、テストに組み込まれました。その理由は、MongoDBを起動して、既存のデータベースを汚染することなく特定の状態にし、一連の操作を実行してから、テストに関係のない任意のデータをふるい分けることなく結果を検査するためです。制御されたテスト環境を維持しながら、それが可能な限り現実的です。
seanhodges 2015年

申し訳ありませんが、「シミュレート」という言葉とこれらすべての「インメモリ」の提案により、Javaランドでの「埋め込み」の意味を忘れてしまいました。それを聞いてうれしい。
ジャクソン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.