javamongodbjunitintegration-testingembedded-database

Embedded MongoDB when running integration tests


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


Solution

  • Here's an updated (for 2022) 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.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());
        }
    
    }