我的问题是 this one 的变体。
由于我的 Java Web 应用程序项目需要大量读取过滤器/查询以及与 GridFS 等工具的接口,因此我正在努力想出一种以上述解决方案建议的方式使用 MongoDB 的明智方法。
因此,我正在考虑在集成测试的同时运行 MongoDB 的嵌入式实例。我希望它自动启动(对于每个测试或整个套件),为每个测试刷新数据库,并在最后关闭。这些测试可能在开发机器和 CI 服务器上运行,所以我的解决方案也需要是可移植的。
任何对 MongoDB 有更多了解的人都可以帮助我了解这种方法的可行性,和/或建议任何可能帮助我入门的阅读材料吗?
我也愿意接受人们可能对我如何解决这个问题提出的其他建议......
我发现 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));
}
}
这是 accepted answer from @rozky 的更新(2022 年)版本(在 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.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());
}
}
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS)
IMongodConfig mongodConfig = new MongodConfigBuilder()
更改为 MongodConfig mongodConfig = MongodConfig.builder()
)。请现在再试一次。
有 Foursquare 产品 Fongo。 Fongo 是 mongo 的内存中 java 实现。它拦截对标准 mongo-java-driver 的调用,用于查找、更新、插入、删除和其他方法。主要用途是用于轻量级单元测试,您不想启动 mongo 进程。
如果您使用的是 Maven,您可能会对我创建的包含 flapdoodle.de 'embedded mongo' API 的插件感兴趣:
嵌入mongo-maven-插件
它提供了一个 start
目标,您可以使用它来启动您想要的任何 MongoDB 版本(例如在 pre-integration-test
期间),以及一个将停止 MongoDB 的 stop
目标(例如在 post-integration-test
期间)。
与其他插件相比,使用此插件的真正好处是不需要事先安装 MongoDB。下载 MongoDB 二进制文件并将其存储在 ~/.embedmongo
中以供将来构建。
使用 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{
}
从版本 3.2.6 开始,您可以在内存中运行 MongoDB。从 site:
从 MongoDB Enterprise 版本 3.2.6 开始,内存存储引擎是 64 位版本中通用可用性 (GA) 的一部分。除了一些元数据和诊断数据,内存存储引擎不维护任何磁盘数据,包括配置数据、索引、用户凭据等。
不仅用于单元测试,还解释了如何将 inmemory mongodb 与 rest api 一起使用。
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>
==================================================== ============================
应用程序属性
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 将下载到以下路径。因此,请考虑该路径具有适当的权限。
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
在生产中,您将使用真实的数据库。
如果您希望您的测试反映您的产品在生产中的行为方式,请使用 Mongo 的真实实例。
伪造的实现可能与真实的实现不完全相同。在测试时,您应该争取正确性。执行速度排在第二位。
不定期副业成功案例分享
com.mongodb
Java API 的一部分,因此它并不比使用常规 API 复杂。