MongoDB yang disematkan saat menjalankan pengujian integrasi

112

Pertanyaan saya adalah variasi dari pertanyaan ini .

Karena proyek aplikasi Web Java saya membutuhkan banyak filter / kueri baca dan antarmuka dengan alat seperti GridFS, saya kesulitan memikirkan cara yang masuk akal untuk menggunakan MongoDB dengan cara yang disarankan solusi di atas.

Oleh karena itu, saya sedang mempertimbangkan untuk menjalankan instance MongoDB yang disematkan bersama tes integrasi saya. Saya ingin ini dimulai secara otomatis (baik untuk setiap pengujian atau seluruh rangkaian), bersihkan database untuk setiap pengujian, dan matikan di akhir. Tes ini mungkin dijalankan pada mesin pengembangan serta server CI, jadi solusi saya juga harus portabel .

Adakah orang yang memiliki lebih banyak pengetahuan tentang MongoDB membantu saya mendapatkan gagasan tentang kelayakan pendekatan ini, dan / atau mungkin menyarankan bahan bacaan apa pun yang dapat membantu saya memulai?

Saya juga terbuka untuk saran lain yang mungkin dimiliki orang tentang bagaimana saya dapat mendekati masalah ini ...

seanhodges
sumber
Jika Anda menggunakan maven, Anda dapat menggunakan mvnrepository.com/artifact/com.wenzani/mongodb-maven-plugin
markdsievers
Anda juga dapat memeriksa proyek ini yang mensimulasikan MongoDB di dalam memori JVM. github.com/thiloplanz/jmockmongo Tapi masih dalam pengembangan.
Sebastien Lorber
Bukan [hanya untuk] untuk pengujian unit, tetapi baca posting blog ini jika Anda ingin menjalankan MongoDB (bahkan cluster) sebagai penerapan dalam memori jika Anda menggunakan Linux. edgystuff.tumblr.com/post/49304254688 Akan sangat bagus untuk memilikinya di luar kotak seperti RavenDB sekalipun.
Tamir
Mirip dengan embedmongo-maven-plugin yang disebutkan di sini, ada juga Plugin Gradle Mongo yang tersedia. Seperti plugin Maven, plugin ini juga membungkus api EmbeddedMongoDb flapdoodle dan memungkinkan Anda menjalankan instance Mongo terkelola dari build Gradle Anda.
Robert Taylor
Periksa contoh kode ini di sini: github.com/familysyan/embedded-mongo-integ . Tanpa instalasi, tanpa ketergantungan. Ini hanyalah skrip semut platform independen yang mengunduh dan mengatur untuk Anda. Itu juga membersihkan semuanya setelah tes Anda.
Edmond

Jawaban:

9

Berikut adalah versi terbaru (untuk 2019) dari jawaban yang diterima dari @rozky (banyak yang telah diubah di pustaka Mongo dan 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());
    }

}
Collin Krawll
sumber
1
Start dan stop berulang dari mongo Tersemat untuk setiap pengujian gagal dalam sebagian besar pengujian. Lebih baik memulai sebelum semua pengujian dan penghentian setelah semua dijalankan
DBS
Anda perlu memasukkan @DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS)bersama dengan perubahan di atas
DBS
@DBS Anda juga dapat menggunakan port acak sehingga Anda masih dapat menjalankan pengujian Anda secara bersamaan pada instance mongo baru yang disematkan. Lihat dokumentasinya di sini .
Collin Krawll
95

Saya telah menemukan pustaka Embedded MongoDB yang terlihat cukup menjanjikan dan melakukan apa yang Anda minta.

Saat ini mendukung versi MongoDB: 1.6.5to 3.1.6, asalkan binari masih tersedia dari mirror yang dikonfigurasi.

Berikut adalah contoh penggunaan singkat, yang baru saja saya coba dan berfungsi dengan sempurna:

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));
    }
}
rozky
sumber
1
Baru saja menggunakan perpustakaan ini dan bekerja dengan sempurna JUnit menguji API Mongo di Mac. Direkomendasikan.
Martin Dow
1
+1 temuan luar biasa! Ketika saya pertama kali mulai menggunakan mongodb setahun yang lalu, tidak memiliki cara terprogram untuk menguji database adalah salah satu kelemahannya. Kami menyiasatinya dengan memiliki contoh pengujian di setiap lingkungan, dikonfigurasi melalui file properti Java tetapi tentu saja itu perlu menginstal mongo di setiap lingkungan. Sepertinya ini akan menyelesaikan semua itu.
andyb
Bagus! menghapus jawaban saya karena tidak lagi akurat. Adakah yang tahu seberapa dewasa ini? Saya bisa membayangkan bahwa mensimulasikan MongoDB pada level yang sangat rendah akan cukup rumit dan dilihat dari sumbernya terlihat level yang cukup tinggi.
Remon van Vliet
Akhirnya harus bermain-main dengan ini dalam proyek saya dan dapat melaporkan bahwa itu sangat mudah diatur dan dijalankan. Panggilan tingkat rendah semuanya adalah bagian dari com.mongodb Java API resmi sehingga tidak lebih rumit daripada menggunakan API biasa.
andyb
17
Berhati-hatilah dengan solusi ini. Itu hanya mengumpulkan informasi tentang sistem operasi saat ini dan mengunduh binari MongoDB spesifik platform yang sesuai dari internet, menjalankan daemon dan melakukan beberapa hal konfigurasi lainnya. Sebagai solusi perusahaan, ini bukan. Mengolok-olok mungkin satu-satunya pilihan nyata.
James Watkins
18

Ada produk Foursquare Fongo . Fongo adalah implementasi java dalam memori dari mongo. Ini memotong panggilan ke mongo-java-driver standar untuk menemukan, memperbarui, menyisipkan, menghapus, dan metode lainnya. Penggunaan utama adalah untuk pengujian unit ringan di mana Anda tidak ingin memutar proses mongo.

zlob
sumber
1
Apakah Fongo kebetulan mencegat panggilan ke jaringan, misalnya ke localhost: 27017 sehingga dapat berfungsi sebagai server palsu drop-in untuk mengaktifkan pengujian integrasi tanpa perubahan kode?
mongo-java-server adalah implementasi server palsu drop-in yang dapat digunakan untuk pengujian integrasi tanpa perubahan kode.
Benedikt Waldvogel
7

Jika Anda menggunakan Maven, Anda mungkin tertarik dengan plugin yang saya buat yang membungkus API 'mongo tertanam' flapdoodle.de :

embedmongo-maven-plugin

Ini memberikan starttujuan yang dapat Anda gunakan untuk memulai versi apa pun dari MongoDB yang Anda inginkan (misalnya selama pre-integration-test), dan stoptujuan yang akan menghentikan MongoDB (misalnya selama post-integration-test).

Manfaat nyata menggunakan plugin ini dibandingkan yang lain adalah tidak ada persyaratan untuk menginstal MongoDB sebelumnya. Biner MongoDB diunduh dan disimpan ~/.embedmongountuk versi mendatang.

joelittlejohn
sumber
Dan inilah versi Clojure untuk Leiningen: github.com/joelittlejohn/lein-embongo
joelittlejohn
4

dengan spring-boot 1.3 Anda dapat menggunakan 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{
}
panci
sumber
1
dapatkah Anda menjelaskan apa yang sebenarnya dilakukan anotasi "@EnableAutoConfiguration (exclude = {EmbeddedMongoAutoConfiguration.class})"?
Bruno Negrão Zica
Alasannya kemungkinan besar karena dependensi de.flapdoodle.embed.mongo tidak ditandai untuk cakupan pengujian. Untuk tidak mengambilnya dan menjalankan mongo tertanam dalam pengaturan aplikasi produksi, pengecualian diperlukan.
Sergey Shcherbakov
3

Anda dapat menjalankan MongoDB di memori mulai versi 3.2.6. Dari situs :

Mulai MongoDB Enterprise versi 3.2.6, mesin penyimpanan dalam memori adalah bagian dari ketersediaan umum (GA) dalam build 64-bit. Selain beberapa metadata dan data diagnostik, mesin penyimpanan dalam memori tidak memelihara data pada disk apa pun, termasuk data konfigurasi, indeks, kredensial pengguna, dll.

Irwin
sumber
1

Tidak hanya untuk unit testing, tapi juga dijelaskan bagaimana cara menggunakan inmemory mongodb dengan rest api.

ketergantungan 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

antarmuka publik UserRepository memperluas MongoRepository {

}

untuk referensi dan semua kode java gunakan tautan di bawah ini: (penjelasan langkah demi langkah)

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

Dheeraj kumar
sumber
0

Performa lebih baik saat dijalankan mongoddenganstorageEngine='ephemeralForTest'

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

Dalam produksi, Anda akan menggunakan database yang sebenarnya.

Jika Anda ingin pengujian Anda mencerminkan bagaimana produk Anda berperilaku dalam produksi, gunakan instance Mongo yang sebenarnya.

Penerapan palsu mungkin tidak berperilaku persis sama dengan yang asli. Saat menguji, Anda harus berusaha untuk kebenaran. Kecepatan eksekusi berada di urutan kedua.

Jackson
sumber
6
Saya pikir Anda melewatkan tujuan saya. Saya tidak mencari contoh palsu dari Mongo, saya ingin contoh nyata tetapi tertanam dalam pengujian saya. Alasannya adalah untuk memulai MongoDB dan memasukkannya ke dalam status tertentu tanpa mencemari database yang ada, menjalankan serangkaian operasi, dan kemudian memeriksa hasilnya tanpa perlu menyaring data sewenang-wenang yang tidak terkait dengan pengujian saya. Senyata mungkin sambil tetap mempertahankan lingkungan pengujian yang terkontrol.
seanhodges
Maaf, kata "simulasikan" dan semua saran "dalam memori" ini membuat saya lupa arti "tertanam" di tanah Jawa. Senang mendengarnya.
Jackson