Entegrasyon testleri çalıştırırken yerleşik MongoDB


112

Sorum bir varyasyonu bu bir .

Java Web uygulaması projem, GridFS gibi araçlarla çok sayıda okuma filtresi / sorgu ve arayüz gerektirdiğinden, yukarıdaki çözümün önerdiği şekilde MongoDB'yi kullanmanın mantıklı bir yolunu bulmakta zorlanıyorum.

Bu nedenle, entegrasyon testlerimin yanında yerleşik bir MongoDB örneği çalıştırmayı düşünüyorum. Ben istiyorum otomatik başlatma (ya her test veya bütün paketi için), veritabanı floş her test için ve kapatılacak sonunda. Bu testler CI sunucusunun yanı sıra geliştirme makinelerinde de çalıştırılabilir, bu nedenle çözümümün de taşınabilir olması gerekecek .

MongoDB hakkında daha fazla bilgiye sahip biri bu yaklaşımın uygulanabilirliği hakkında fikir edinmeme yardım edebilir mi ve / veya belki de başlamama yardımcı olabilecek herhangi bir okuma materyali önerebilir mi?

Ayrıca insanların bu soruna nasıl yaklaşabileceğime dair sahip olabileceği diğer önerilere de açığım ...


Maven kullanıyorsanız, bizimkini kullanabilirsiniz mvnrepository.com/artifact/com.wenzani/mongodb-maven-plugin
markdsievers

JVM belleği içinde MongoDB'yi simüle eden bu projeyi de kontrol edebilirsiniz. github.com/thiloplanz/jmockmongo Ancak hala geliştirme aşamasındadır.
Sebastien Lorber

[Sadece birim testleri için] değil, Linux kullanıyorsanız, MongoDB'yi (hatta bir küme) bellek içi dağıtım olarak çalıştırmak istiyorsanız bu blog gönderisini okuyun. edgystuff.tumblr.com/post/49304254688 Yine de RavenDB gibi kutunun dışında olması harika olurdu.
Tamir

Burada bahsedilen embedmongo-maven-eklentisine benzer şekilde, bir Gradle Mongo Eklentisi de mevcuttur. Maven eklentisi gibi, flapdoodle EmbeddedMongoDb api'sini de sarar ve Gradle derlemelerinizden yönetilen bir Mongo örneği çalıştırmanıza izin verir.
Robert Taylor

Bu kod örneğini şuradan kontrol edin: github.com/familysyan/embedded-mongo-integ . Kurulum yok, bağımlılık yok. Bu, sizin için indirip kuran, platformdan bağımsız bir karınca betiğidir. Ayrıca testlerinizden sonra her şeyi temizler.
Edmond

Yanıtlar:


9

İşte @rozky'den kabul edilen yanıtın güncellenmiş (2019 için) versiyonu ( hem Mongo hem de Gömülü MongoDB kütüphanelerinde çok şey değişti).

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
Her test için Gömülü mongo'nun tekrarlanan başlatma ve durdurma çoğu testte başarısız olur. Tüm testlerden önce başlamak ve tümü uygulandıktan sonra kapatmak daha iyidir
DBS

@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS)Yukarıdaki değişiklikle birlikte eklemeniz gerekir
DBS

@DBS Testlerinizi yeni gömülü bir mongo örneğinde eşzamanlı olarak çalıştırabilmek için rastgele bir bağlantı noktası da kullanabilirsiniz. Dokümanlara buradan bakın .
Collin Krawll

95

Oldukça umut verici görünen ve istediğinizi yapan Gömülü MongoDB kitaplığı buldum .

Şu anda MongoDB sürümlerini destekliyor: 1.6.5için 3.1.6, ikili dosyaların yapılandırılmış yansıtmadan hala kullanılabilir olması koşuluyla.

İşte yeni denediğim ve mükemmel bir şekilde çalışan kısa kullanım örneği:

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
Sadece bu kitaplığı kullandım ve JUnit bir Mac üzerinde Mongo API testinde mükemmel çalıştı. Önerilen.
Martin Dow

1
+1 mükemmel keşif! Bir yıl önce mongodb'u ilk kullanmaya başladığımda, bir veritabanına karşı test etmenin programlı bir yolunun olmaması dezavantajlardan biriydi. Bunu, her ortamda bir Java özellikler dosyasıyla yapılandırılan, ancak elbette her ortama mongo'nun kurulu olması gereken bir test örneğine sahip olarak aştık. Bu, tüm bunları çözecek gibi görünüyor.
andyb

Güzel! artık doğru olmadığı için cevabımı sildim. Bunun ne kadar olgun olduğunu bilen var mı? MongoDB'yi çok düşük bir seviyede simüle etmenin oldukça karmaşık olacağını ve kaynaktan bakıldığında oldukça yüksek seviyede göründüğünü hayal edebiliyorum.
Remon van Vliet

Sonunda projemde bununla oynadım ve kurulumunun ve çalıştırmanın inanılmaz derecede kolay olduğunu bildirebilirim. Düşük seviyeli çağrıların tümü resmi com.mongodb Java API'sinin bir parçasıdır, bu nedenle normal API kullanmaktan daha karmaşık değildir.
andyb

17
Bu çözüme dikkat edin. Yalnızca mevcut işletim sistemi hakkında bilgi toplar ve uygun platforma özgü MongoDB ikili dosyalarını internetten indirir, daemon'u çalıştırır ve bazı diğer yapılandırma işlerini yapar. Kurumsal bir çözüm olarak bu değil. Alay etmek tek gerçek seçenek olabilir.
James Watkins

18

Foursquare ürünü Fongo var . Fongo, mongo'nun bellek içi bir java uygulamasıdır. Bulma, güncelleme, ekleme, çıkarma ve diğer yöntemler için standart mongo-java sürücüsüne yapılan çağrıları keser. Birincil kullanım, mongo sürecini hızlandırmak istemediğiniz hafif birim testi içindir.


1
Fongo, kod değişiklikleri olmadan entegrasyon testini mümkün kılmak için sahte bir sunucu olarak hizmet edebilmesi için, örneğin localhost: 27017 gibi ağa yapılan çağrıları engelliyor mu?

mongo-java-server , kod değişikliği yapmadan entegrasyon testi için kullanılabilen bir drop-in sahte sunucu uygulamasıdır.
Benedikt Waldvogel

7

Maven kullanıyorsanız, flapdoodle.de 'gömülü mongo' API'sini saran, oluşturduğum bir eklenti ilginizi çekebilir :

embedmongo-maven-eklentisi

startMongoDB'nin istediğiniz herhangi bir sürümünü başlatmak için kullanabileceğiniz bir hedef (örneğin sırasında pre-integration-test) ve stopMongoDB'yi durduracak bir hedef (örneğin sırasında post-integration-test) sağlar.

Bu eklentiyi kullanmanın diğerlerine göre gerçek yararı, MongoDB'nin önceden kurulmasına gerek olmamasıdır. MongoDB ikili dosyaları indirilir ve ~/.embedmongogelecekteki yapılar için saklanır .


Ve işte Leiningen için Clojure sürümü: github.com/joelittlejohn/lein-embongo
joelittlejohn


4

Spring-boot 1.3 ile EmbeddedMongoAutoConfiguration'ı kullanabilirsiniz

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})" ek açıklamasının gerçekte ne yaptığını açıklayabilir misiniz?
Bruno Negrão Zica

Bunun nedeni büyük olasılıkla de.flapdoodle.embed.mongo bağımlılığının test kapsamı için işaretlenmemiş olmasıdır. Onu alıp üretim uygulaması kurulumunda gömülü mongo çalıştırmamak için dışlama gereklidir.
Sergey Shcherbakov

3

MongoDB'yi 3.2.6 sürümünden itibaren bellekte çalıştırabilirsiniz. Gönderen sitede :

MongoDB Enterprise sürüm 3.2.6'dan başlayarak, bellek içi depolama motoru, 64 bit yapılarda genel kullanılabilirliğin (GA) bir parçasıdır. Bellek içi depolama motoru, bazı meta veriler ve tanılama verilerinin dışında, yapılandırma verileri, dizinler, kullanıcı kimlik bilgileri vb. Dahil olmak üzere disk üzerinde herhangi bir veri tutmaz.


1

Sadece birim testi için değil, aynı zamanda bellek içi mongodb'nin rest api ile nasıl kullanılacağını da açıkladı.

maven bağımlılığı:

        <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

public arayüz UserRepository, MongoRepository'yi genişletir {

}

referans ve tüm java kodu için aşağıdaki bağlantıyı kullanın: (adım adım açıklama)

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


0

Çalıştırırken Performanslar iyidir mongodilestorageEngine='ephemeralForTest'

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

-1

Üretimde gerçek bir veritabanı kullanacaksınız.

Testlerinizin ürününüzün üretimde nasıl davrandığını yansıtmasını istiyorsanız gerçek bir Mongo örneği kullanın.

Sahte bir uygulama gerçek olanla tam olarak aynı davranmayabilir. Test ederken, doğruluk için çabalamalısınız. İcra hızı ikinci sırada geliyor.


6
Sanırım amacımı kaçırdın. Sahte bir Mongo örneği aramıyordum, gerçek bir örnek istedim ama testlerime dahil ettim. Bunun nedeni, MongoDB'yi başlatmak ve mevcut bir veritabanını kirletmeden belirli bir duruma sokmak, bir dizi işlem yürütmek ve ardından testimle ilgisi olmayan keyfi verileri elemek zorunda kalmadan sonucu incelemekti. Yine de kontrollü bir test ortamını korurken olabildiğince gerçek.
seanhodges

Üzgünüm, "simüle et" kelimesi ve tüm bu "bellek içi" öneriler Java ülkesinde "gömülü" kelimesinin anlamını unutmama neden oldu. Duyduğuma sevindim.
Jackson
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.