My question is a variation of this one.
Since my Java Web-app project requires a lot of read filters/queries and interfaces with tools like GridFS, I'm struggling to think of a sensible way to employ MongoDB in the way the above solution suggests.
Therefore, I'm considering running an embedded instance of MongoDB alongside my integration tests. I'd like it to start up automatically (either for each test or the whole suite), flush the database for every test, and shut down at the end. These tests might be run on development machines as well as the CI server, so my solution will also need to be portable.
Can anyone with more knowledge on MongoDB help me get idea of the feasibility of this approach, and/or perhaps suggest any reading material that might help me get started?
I'm also open to other suggestions people might have on how I could approach this problem...
Here's an updated (for 2019) version of the accepted answer from @rozky (a lot has been changed in both the Mongo and Embedded MongoDB libraries).
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());
}
}
I have found Embedded MongoDB library which looks quite promising and does what you have asked for.
Currently supports MongoDB versions: 1.6.5
to 3.1.6
, provided the binaries are still available from the configured mirror.
Here is short example of use, which I have just tried and it works perfectly:
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
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.
来源:https://stackoverflow.com/questions/6437226/embedded-mongodb-when-running-integration-tests