Programing

통합 테스트를 실행할 때 임베디드 MongoDB

crosscheck 2020. 8. 6. 07:56
반응형

통합 테스트를 실행할 때 임베디드 MongoDB


내 질문의 변형 이 하나 .

Java 웹 응용 프로그램 프로젝트에는 많은 읽기 필터 / 쿼리와 GridFS와 같은 도구와의 인터페이스가 필요하므로 위의 솔루션이 제안하는 방식으로 MongoDB를 사용하는 합리적인 방법을 생각하는 데 어려움을 겪고 있습니다.

따라서 통합 테스트와 함께 MongoDB의 임베디드 인스턴스를 실행하는 것을 고려하고 있습니다. 각 테스트 또는 전체 제품군에 대해 자동으로 시작하고 모든 테스트에 대해 데이터베이스플러시 하고 마지막에 종료 하고 싶습니다 . 이 테스트는 CI 서버뿐만 아니라 개발 시스템에서도 실행될 수 있으므로 솔루션도 이식 가능 해야합니다 .

MongoDB에 대해 더 많은 지식을 가진 사람이이 접근 방식의 실현 가능성을 이해하는 데 도움을 줄 수 있습니까?

또한이 문제에 어떻게 접근 할 수 있는지 사람들이 가질 수있는 다른 제안에도 공개되어 있습니다 ...


@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());
    }

}

나는 유망하게 보이고 당신이 요청한 것을하는 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));
    }
}

There is Foursquare product Fongo. Fongo is an in-memory java implementation of mongo. It intercepts calls to the standard mongo-java-driver for finds, updates, inserts, removes and other methods. The primary use is for lightweight unit testing where you don't want to spin up a mongo process.


If you're using Maven you may be interested in a plugin I've created that wraps the flapdoodle.de 'embedded mongo' API:

embedmongo-maven-plugin

It provides a start goal that you can use to start any version of MongoDB you want (e.g. during pre-integration-test), and a stop goal that will stop MongoDB (e.g. during post-integration-test).

The real benefit of using this plugin over others is that there is no requirement for MongoDB to be installed beforehand. MongoDB binaries are downloaded and stored in ~/.embedmongo for future builds.


If you are using sbt and specs2, I wrote the same kind of wrapper for embedmongo

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


with spring-boot 1.3 you can use 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{
}

You can run MongoDB in memory as of version 3.2.6. From the site:

Starting in MongoDB Enterprise version 3.2.6, the in-memory storage engine is part of general availability (GA) in the 64-bit builds. Other than some metadata and diagnostic data, the in-memory storage engine does not maintain any on-disk data, including configuration data, indexes, user credentials, etc.


If you are using maven, you can use ours http://mvnrepository.com/artifact/com.wenzani/mongodb-maven-plugin


You can also check this project which simulate a MongoDB inside JVM memory. https://github.com/thiloplanz/jmockmongo But it is still in development.


Not [just for] for unit testings, but read this blog post if you like to run MongoDB (even a cluster) as in-memory deployment if you're using Linux.

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

Would be great to have it out of the box like RavenDB though.


Similar to the embedmongo-maven-plugin mentioned here, there is also a Gradle Mongo Plugin available.

Like the Maven plugin it also wraps the flapdoodle EmbeddedMongoDb api and allows you to run a managed instance of Mongo from your Gradle builds.


Check this code example here: https://github.com/familysyan/embedded-mongo-integ. No installation, no dependency. It's simply a platform independent ant script that do download and setup for you. It also cleans up everything after your tests.


In production, you will be using a real database.

If you want your tests to reflect how your product behaves in production, use a real instance of Mongo.

A fake implementation may not behave exactly the same as a real one. When testing, you should strive for correctness. Speed of execution comes second.

참고URL : https://stackoverflow.com/questions/6437226/embedded-mongodb-when-running-integration-tests

반응형