통합 테스트 실행시 포함 된 MongoDB


112

내 질문의 변형 이 일 .

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

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

MongoDB에 대해 더 많은 지식을 가진 사람이이 접근 방식의 타당성에 대한 아이디어를 얻도록 도와 줄 수 있고 / 또는 시작하는 데 도움이 될만한 읽기 자료를 제안 할 수 있습니까?

나는 또한 사람들이이 문제에 어떻게 접근 할 수 있는지에 대한 다른 제안에 열려 있습니다.


당신이 받는다는을 사용하는 경우, 당신은 우리의 사용할 수 있습니다 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 와 같이 상자에서 꺼내면 좋을 것입니다.
Tamir 2013 년

여기에 언급 된 embedmongo-maven-plugin과 유사하게 Gradle Mongo 플러그인도 사용할 수 있습니다. Maven 플러그인과 마찬가지로 flapdoodle EmbeddedMongoDb API를 래핑하고 Gradle 빌드에서 관리되는 Mongo 인스턴스를 실행할 수 있습니다.
Robert Taylor

여기에서이 코드 예제를 확인하십시오 : github.com/familysyan/embedded-mongo-integ . 설치, 의존성 없음. 다운로드 및 설정을 수행하는 플랫폼 독립적 인 개미 스크립트입니다. 또한 테스트 후 모든 것을 정리합니다.
Edmond

답변:


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 2019

95

나는 발견했다 임베디드 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
이 라이브러리를 사용하고 Mac에서 Mongo API를 테스트하는 JUnit이 완벽하게 작동했습니다. 추천합니다.
Martin Dow

1
+1 훌륭한 찾기! 1 년 전 mongodb를 처음 사용하기 시작했을 때 데이터베이스에 대해 테스트하는 프로그래밍 방식이 없다는 것이 단점 중 하나였습니다. 우리는 Java 속성 파일을 통해 구성된 모든 환경에서 테스트 인스턴스를 사용하여이 문제를 해결했지만 물론 모든 환경에 mongo를 설치해야했습니다. 이것은 모든 것을 해결할 것 같습니다.
andyb

좋은! 더 이상 정확하지 않기 때문에 내 대답을 삭제했습니다. 이게 얼마나 성숙했는지 아는 사람 있나요? 매우 낮은 수준에서 MongoDB를 시뮬레이션해야하는 것은 매우 복잡하고 소스에서 판단하면 꽤 높은 수준으로 보일 것이라고 상상할 수 있습니다.
Remon van Vliet 2012-06-27

마침내 내 프로젝트에서 이것을 가지고 놀았고 설정과 실행이 매우 쉬웠다 고보고 할 수 있습니다. 저수준 호출은 모두 공식 com.mongodb Java API의 일부 이므로 일반 API를 사용하는 것보다 복잡하지 않습니다.
andyb

17
이 솔루션에주의하십시오. 현재 운영 체제에 대한 정보를 수집하고 인터넷에서 적절한 플랫폼 별 MongoDB 바이너리를 다운로드하고 데몬을 실행하며 다른 구성 작업을 수행합니다. 엔터프라이즈 솔루션 으로서는 그렇지 않습니다. 조롱이 유일한 선택 일 수 있습니다.
James Watkins

18

Foursquare 제품 Fongo가 있습니다. Fongo는 mongo의 메모리 내 Java 구현입니다. 찾기, 업데이트, 삽입, 제거 및 기타 메소드를 위해 표준 mongo-java-driver에 대한 호출을 가로 챕니다. 주요 용도는 몽고 프로세스를 가동하고 싶지 않은 경량 단위 테스트입니다.


1
Fongo는 코드 변경없이 통합 테스트를 가능하게하는 드롭 인 가짜 서버 역할을 할 수 있도록 localhost : 27017과 같은 네트워크 호출을 가로 채나요?

mongo-java-server 는 코드 변경없이 통합 테스트에 사용할 수있는 드롭 인 가짜 서버 구현입니다.
Benedikt Waldvogel 2018

7

Maven을 사용하는 경우 flapdoodle.de 'embedded mongo'API 를 래핑하는 내가 만든 플러그인에 관심이있을 수 있습니다 .

embedmongo-maven-plugin

start원하는 MongoDB 버전을 시작하는 데 사용할 수 있는 목표 (예 :)와 MongoDB를 중지 pre-integration-teststop목표 (예 :)를 제공 post-integration-test합니다.

이 플러그인을 다른 플러그인에 비해 사용하는 실제 이점은 MongoDB를 미리 설치할 필요가 없다는 것입니다. MongoDB 바이너리는 ~/.embedmongo향후 빌드 를 위해 다운로드되고 저장됩니다 .


그리고 여기 Leiningen의 Clojure 버전이 있습니다 : github.com/joelittlejohn/lein-embongo
joelittlejohn


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})"주석이 실제로 무엇을하는지 설명해 주시겠습니까?
Bruno Negrão Zica 2018

그 이유는 아마도 테스트 범위에 대해 표시되지 않은 de.flapdoodle.embed.mongo 종속성 때문일 것입니다. 그것을 집어 들고 프로덕션 응용 프로그램 설정에서 임베디드 mongo를 실행하지 않으려면 제외가 필요합니다.
Sergey Shcherbakov

3

버전 3.2.6부터 메모리에서 MongoDB를 실행할 수 있습니다. 로부터 사이트 :

MongoDB Enterprise 버전 3.2.6부터 메모리 내 스토리지 엔진은 64 비트 빌드에서 GA (일반 가용성)의 일부입니다. 일부 메타 데이터 및 진단 데이터를 제외하고 메모리 내 스토리지 엔진은 구성 데이터, 인덱스, 사용자 자격 증명 등을 포함한 디스크 데이터를 유지하지 않습니다.


1

단위 테스트뿐만 아니라 나머지 API와 함께 inmemory mongodb를 사용하는 방법도 설명했습니다.

메이븐 종속성 :

        <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 인스턴스를 사용하세요.

가짜 구현은 실제 구현과 정확히 동일하게 작동하지 않을 수 있습니다. 테스트 할 때 정확성을 위해 노력해야합니다. 실행 속도가 두 번째입니다.


6
내 목적을 놓친 것 같아요. Mongo의 가짜 인스턴스를 찾고있는 것이 아니라 실제 인스턴스를 원했지만 테스트에 포함되었습니다. 그 이유는 MongoDB를 시작하고 기존 데이터베이스를 오염시키지 않고 특정 상태로 만들고 일련의 작업을 실행 한 다음 내 테스트와 관련이없는 임의의 데이터를 검색 할 필요없이 결과를 검사하기 위해서였습니다. 통제 된 테스트 환경을 유지하면서 가능한 한 현실적입니다.
seanhodges

죄송합니다. "simulate"라는 단어와 이러한 모든 "인 메모리"제안으로 인해 Java-land에서 "embedded"의 의미를 잊어 버렸습니다. 그것을 듣고 기뻐.
Jackson
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.