运行集成测试时嵌入式 MongoDB

我的问题是 这个的一个变体。

由于我的 Java Web 应用程序项目需要大量的读过滤器/查询以及使用 GridFS 等工具的接口,因此我很难想出一种合理的方法来按照上述解决方案的建议来使用 MongoDB。

因此,我正在考虑在集成测试的同时运行 MongoDB 的嵌入式实例。我希望它是 自动启动(对于每个测试或整个套件) ,对于每个测试是 清查数据库,最后是 关闭。这些测试可以在开发机器上运行,也可以在 CI 服务器上运行,因此我的解决方案也需要是 便携式的

任何对 MongoDB 有更多了解的人都可以帮助我了解这种方法的可行性,并且/或者建议任何可以帮助我开始的阅读材料吗?

我也愿意听取其他人对我如何处理这个问题的建议..。

100043 次浏览

我已经找到了 嵌入式 MongoDB库,看起来相当有前途,并做你所要求的。

目前支持 MongoDB 版本: 从 1.6.53.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));
}
}

如果你正在使用 Maven,你可能会对我创建的一个包装 Flapdodle.de’em bed mongo’API的插件感兴趣:

嵌入式 mongo-maven-plugin

它提供了一个 start目标,您可以使用它来启动任何您想要的 MongoDB 版本(例如在 pre-integration-test期间) ,以及一个 stop目标,该目标将停止 MongoDB (例如在 post-integration-test期间)。

与其他插件相比,使用这个插件的真正好处是不需要事先安装 MongoDB。MongoDB 二进制文件被下载并存储在 ~/.embedmongo中,以备将来构建时使用。

如果您正在使用 sbt 和 specs2,那么我为嵌入式 mongo 编写了同样的包装器

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

还有 Foursquare 的产品 Fongo。 Fongo 是 mongo 的内存 Java 实现。它拦截对标准 mongo-java 驱动程序的调用,用于查找、更新、插入、移除和其他方法。其主要用途是进行轻量级单元测试,您不希望在这种情况下启动 mongo 进程。

在生产环境中,您将使用一个真正的数据库。

如果希望测试反映产品在生产环境中的行为,请使用 Mongo 的一个真实实例。

假实现的行为可能与真实实现的行为不完全一样。在测试时,您应该力求正确。执行速度第二。

使用弹簧启动1.3,你可以使用 嵌入式 MongoAutoConfiguration

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{
}

从3.2.6版本开始,您可以在内存中运行 MongoDB:

从 MongoDB 企业版3.2.6开始,内存中的存储 在64位版本中,引擎是通用可用性(GA)的一部分。 除了一些元数据和诊断数据之外,内存中的存储 引擎不维护任何磁盘上的数据,包括配置 数据、索引、用户凭据等。

下面是 接受@rozky 的回答的更新版本(针对2022年)(Mongo 和嵌入式 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.MongodConfig;
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;
MongodConfig mongodConfig = MongodConfig.builder()
.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());
}


}

不仅用于单元测试,还解释了如何将 inmemory mongodb 与 rest api 一起使用。

专家依赖性:

        <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>

=============================================================================

应用性能

server.port = 8080
spring.data.mongodb.database=user_db
spring.data.mongodb.port=27017
spring.data.mongodb.host=localhost

=============================================================================

Java

公共接口 UserRepository 扩展 MongoRepository {

}

以下链接供参考和所有 Java 代码使用: (逐步解释)

Https://www.youtube.com/watch?v=2tq2q7ezhsa&t=7s

使用 storageEngine='ephemeralForTest'执行 mongod时性能更好

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

要运行嵌入式 mongodb 进行集成测试,以下是所需的 maven 依赖项:

        <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
<version>2.5.2</version>
</dependency>


<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
<version>2.5.2</version>
</dependency>


<dependency>
<groupId>de.flapdoodle.embed</groupId>
<artifactId>de.flapdoodle.embed.mongo</artifactId>
<version>3.0.0</version>
<scope>test</scope>
</dependency>

尝试使用下面为 EmbeddedMongoAutoConfiguration剪切的代码:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.mongo.MongoProperties;
import org.springframework.boot.autoconfigure.mongo.embedded.EmbeddedMongoAutoConfiguration;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;


@SpringBootApplication
public class EmbeddedMongoApplication {


public static void main(String[] args) {
System.setProperty("os.arch", "x86_64");
SpringApplication.run(EmbeddedMongoApplication.class, args);
}
    

@Bean
public EmbeddedMongoAutoConfiguration embeddedMongoAutoConfiguration(MongoProperties mongoProperties) {
return new EmbeddedMongoAutoConfiguration(mongoProperties);
}
}

注:

嵌入式 mongodb 将被下载到 Path 的下方,因此请考虑路径是否具有适当的权限。

Linux : $HOME/.embedmongo/linux/mongodb-linux-x86_64-3.2.2.tgz
Windows : C:\Users\<username>\.embedmongo\win32\mongodb-win32-x86_64-3.x.x.zip