Đã nhúng MongoDB khi chạy thử nghiệm tích hợp


112

Câu hỏi của tôi là một biến thể của câu hỏi này .

Vì dự án Java Web-app của tôi yêu cầu rất nhiều bộ lọc / truy vấn đọc và giao diện với các công cụ như GridFS, tôi đang đấu tranh để nghĩ ra một cách hợp lý để sử dụng MongoDB theo cách mà giải pháp trên gợi ý.

Do đó, tôi đang xem xét chạy một phiên bản được nhúng của MongoDB cùng với các bài kiểm tra tích hợp của mình. Tôi muốn nó tự động khởi động (cho mỗi bài kiểm tra hoặc cho cả bộ), xóa cơ sở dữ liệu cho mỗi bài kiểm tra và tắt khi kết thúc. Các bài kiểm tra này có thể được chạy trên các máy phát triển cũng như máy chủ CI, vì vậy giải pháp của tôi cũng cần phải có tính di động .

Bất kỳ ai có thêm kiến ​​thức về MongoDB có thể giúp tôi hình dung về tính khả thi của phương pháp này và / hoặc có thể đề xuất bất kỳ tài liệu đọc nào có thể giúp tôi bắt đầu không?

Tôi cũng sẵn sàng đón nhận những gợi ý khác mà mọi người có thể có về cách tôi có thể tiếp cận vấn đề này ...


Nếu bạn đang sử dụng maven, bạn có thể sử dụng chúng ta mvnrepository.com/artifact/com.wenzani/mongodb-maven-plugin
markdsievers

Bạn cũng có thể kiểm tra dự án này mô phỏng MongoDB bên trong bộ nhớ JVM. github.com/thiloplanz/jmockmongo Nhưng nó vẫn đang được phát triển.
Sebastien Lorber

Không phải [chỉ dành cho] cho các thử nghiệm đơn vị, nhưng hãy đọc bài đăng blog này nếu bạn muốn chạy MongoDB (thậm chí là một cụm) dưới dạng triển khai trong bộ nhớ nếu bạn đang sử dụng Linux. edgystuff.tumblr.com/post/49304254688 Tuy nhiên, sẽ rất tuyệt nếu có nó ngay từ đầu như RavenDB.
Tamir

Tương tự như nhúngmongo-maven-plugin được đề cập ở đây, cũng có sẵn một Plugin Gradle Mongo . Giống như plugin Maven, nó cũng bao bọc api Flapdoodle EmbeddedMongoDb và cho phép bạn chạy phiên bản Mongo được quản lý từ các bản dựng Gradle của bạn.
Robert Taylor

Kiểm tra ví dụ mã này tại đây: github.com/familysyan/embedded-mongo-integ . Không cần cài đặt, không phụ thuộc. Nó chỉ đơn giản là một tập lệnh kiến ​​độc lập với nền tảng có thể tải xuống và thiết lập cho bạn. Nó cũng làm sạch mọi thứ sau các thử nghiệm của bạn.
Edmond

Câu trả lời:


9

Đây là phiên bản cập nhật (cho năm 2019) của câu trả lời được chấp nhận từ @rozky (nhiều thứ đã được thay đổi trong cả thư viện Mongo và 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
Bắt đầu và dừng lặp lại mongo được nhúng cho mỗi thử nghiệm không thành công hầu hết các thử nghiệm. Tốt hơn hết là nên bắt đầu trước khi tất cả các thử nghiệm và tắt máy sau khi tất cả đã được thực thi
DBS

Bạn cần phải bao gồm @DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS)cùng với thay đổi ở trên
DBS

@DBS Bạn cũng có thể sử dụng một cổng ngẫu nhiên để bạn vẫn có thể chạy các thử nghiệm của mình đồng thời trên một phiên bản mongo mới được nhúng. Xem tài liệu tại đây .
Collin Krawll,

95

Tôi đã tìm thấy thư viện Embedded MongoDB trông khá hứa hẹn và thực hiện được những gì bạn yêu cầu.

Hiện tại hỗ trợ các phiên bản MongoDB: 1.6.5với 3.1.6điều kiện là các tệp nhị phân vẫn có sẵn từ máy nhân bản đã định cấu hình.

Đây là ví dụ ngắn gọn về cách sử dụng mà tôi vừa thử và nó hoạt động hoàn hảo:

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
Chỉ cần sử dụng thư viện này và nó hoạt động hoàn hảo. JUnit đang thử nghiệm API Mongo trên máy Mac. Được đề xuất.
Martin Dow

1
+1 tìm thấy xuất sắc! Khi tôi lần đầu tiên bắt đầu sử dụng mongodb cách đây một năm, việc không có cách lập trình để kiểm tra cơ sở dữ liệu là một trong những nhược điểm. Chúng tôi đã giải quyết vấn đề này bằng cách có một phiên bản thử nghiệm trên mọi môi trường, được định cấu hình thông qua tệp thuộc tính Java nhưng tất nhiên cần phải cài đặt mongo trên mọi môi trường. Điều này có vẻ như nó sẽ giải quyết tất cả những điều đó.
andyb

Đẹp! đã xóa câu trả lời của tôi vì nó không còn chính xác nữa. Bất cứ ai có ý tưởng làm thế nào trưởng thành này là? Tôi có thể tưởng tượng việc phải mô phỏng MongoDB ở mức rất thấp sẽ khá phức tạp và đánh giá từ nguồn thì nó có vẻ khá cao.
REMON van Vliet

Cuối cùng thì tôi cũng phải làm với điều này trong dự án của mình và có thể báo cáo rằng nó cực kỳ dễ thiết lập và chạy. Các lệnh gọi cấp thấp đều là một phần của com.mongodb API Java chính thức nên không phức tạp hơn so với việc sử dụng API thông thường.
andyb,

17
Hãy cẩn thận với giải pháp này. Nó chỉ thu thập thông tin về hệ điều hành hiện tại và tải xuống các tệp nhị phân MongoDB dành riêng cho nền tảng thích hợp từ internet, chạy daemon và thực hiện một số công cụ cấu hình khác. Là một giải pháp doanh nghiệp, điều này không phải là. Chế nhạo có thể là lựa chọn thực sự duy nhất.
James Watkins

18

Có sản phẩm Foursquare Fongo . Fongo là một triển khai java trong bộ nhớ của mongo. Nó chặn các cuộc gọi tới trình điều khiển mongo-java tiêu chuẩn để tìm, cập nhật, chèn, loại bỏ và các phương thức khác. Việc sử dụng chính là để kiểm tra đơn vị nhẹ, nơi bạn không muốn tạo ra một quy trình mongo.


1
Fongo có tình cờ chặn các cuộc gọi đến mạng, ví dụ như tới localhost: 27017 để nó có thể hoạt động như một máy chủ giả mạo để cho phép kiểm tra tích hợp mà không cần thay đổi mã không?

mongo-java-server là một triển khai máy chủ giả mạo có thể được sử dụng để kiểm tra tích hợp mà không cần thay đổi mã.
Benedikt Waldvogel

7

Nếu bạn đang sử dụng Maven, bạn có thể quan tâm đến một plugin mà tôi đã tạo để bao bọc API 'mongo được nhúng' của flapdoodle.de :

nhúngmongo-maven-plugin

Nó cung cấp một startmục tiêu mà bạn có thể sử dụng để bắt đầu bất kỳ phiên bản MongoDB nào mà bạn muốn (ví dụ: trong khi pre-integration-test) và một stopmục tiêu sẽ dừng MongoDB (ví dụ: trongpost-integration-test ).

Lợi ích thực sự của việc sử dụng plugin này so với các plugin khác là không có yêu cầu cài đặt trước MongoDB. Các tệp nhị phân MongoDB được tải xuống và lưu trữ trong ~/.embedmongocác bản dựng sau này.


Và đây là phiên bản Clojure cho Leiningen: github.com/joelittlejohn/lein-embongo
joelittlejohn


4

với spring-boot 1.3, bạn có thể sử dụng 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
bạn có thể giải thích chú thích "@EnableAutoConfiguration (lude = {EmbeddedMongoAutoConfiguration.class})" thực sự đang làm gì không?
Bruno Negrão Zica

Lý do rất có thể là sự phụ thuộc de.flapdoodle.embed.mongo không được đánh dấu cho phạm vi thử nghiệm. Không phải chọn nó và chạy mongo nhúng trong thiết lập ứng dụng sản xuất, loại trừ là cần thiết.
Sergey Shcherbakov

3

Bạn có thể chạy MongoDB trong bộ nhớ kể từ phiên bản 3.2.6. Từ trang web :

Bắt đầu từ phiên bản MongoDB Enterprise 3.2.6, công cụ lưu trữ trong bộ nhớ là một phần của tính khả dụng chung (GA) trong các bản dựng 64 bit. Ngoài một số siêu dữ liệu và dữ liệu chẩn đoán, công cụ lưu trữ trong bộ nhớ không duy trì bất kỳ dữ liệu nào trên đĩa, bao gồm dữ liệu cấu hình, chỉ mục, thông tin đăng nhập của người dùng, v.v.


1

Không chỉ để thử nghiệm đơn vị mà còn giải thích cách sử dụng mongodb inmemory với api phần còn lại.

sự phụ thuộc của 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

giao diện công khai UserRepository mở rộng MongoRepository {

}

để tham khảo và sử dụng tất cả mã java liên kết dưới đây: (giải thích từng bước)

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


0

Hiệu suất tốt hơn khi thực hiện mongodvớistorageEngine='ephemeralForTest'

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

-1

Trong quá trình sản xuất, bạn sẽ sử dụng cơ sở dữ liệu thực.

Nếu bạn muốn các bài kiểm tra của mình phản ánh cách sản phẩm của bạn hoạt động trong quá trình sản xuất, hãy sử dụng phiên bản thực của Mongo.

Việc triển khai giả mạo có thể không hoạt động hoàn toàn giống như một triển khai thật. Khi thử nghiệm, bạn nên cố gắng để đạt được sự đúng đắn. Tốc độ thực hiện đứng thứ hai.


6
Tôi nghĩ rằng bạn đã bỏ lỡ mục đích của tôi. Tôi không tìm kiếm một phiên bản giả mạo của Mongo, tôi muốn một phiên bản thực nhưng được nhúng trong các bài kiểm tra của tôi. Lý do là để khởi động MongoDB và đặt nó vào một trạng thái cụ thể mà không gây ô nhiễm cơ sở dữ liệu hiện có, chạy một loạt hoạt động và sau đó kiểm tra kết quả mà không cần sàng lọc dữ liệu tùy ý không liên quan đến thử nghiệm của tôi. Nó giống như thật trong khi vẫn duy trì một môi trường thử nghiệm được kiểm soát.
seanhodges

Xin lỗi, từ "mô phỏng" và tất cả các đề xuất "trong bộ nhớ" này đã khiến tôi quên mất ý nghĩa của "nhúng" trong Java-land. Rất vui khi nghe nó.
Jackson
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.