The easiest way to configure Embedded MongoDB

13,162

Solution 1

The flapdoodle embedded MongoDB can be integrated with Spring Boot.

  • Declare a dependency on flapdoodle:

    <dependency>
        <groupId>de.flapdoodle.embed</groupId>
        <artifactId>de.flapdoodle.embed.mongo</artifactId>
        <version>2.0.0</version>
    </dependency>
    
  • Declare a dependency on the library, to provide a Spring factory bean for flapdoodle's embedded MongoDB:

    <dependency>
        <groupId>cz.jirutka.spring</groupId>
        <artifactId>embedmongo-spring</artifactId>
        <version>1.3.1</version>
    </dependency>
    
  • Presumably, you have already declared a dependency on spring-boot-starter-data-mongodb:

    <dependency>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-data-mongodb</artifactId>
    </dependency>
    
  • Now, just configure a MongoTemplate pointing at the embedded MongoDB instance:

    @Bean
    public MongoTemplate mongoTemplate() throws IOException {
        EmbeddedMongoFactoryBean mongo = new EmbeddedMongoFactoryBean();
        mongo.setBindIp("localhost");
        MongoClient mongoClient = mongo.getObject();
        MongoTemplate mongoTemplate = new MongoTemplate(mongoClient, "test_or_whatever_you_want_to_call_this_db");
        return mongoTemplate;
    }
    

Solution 2

For Spring Boot 2.2.x with JUnit5

pom.xml

       <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>de.flapdoodle.embed</groupId>
            <artifactId>de.flapdoodle.embed.mongo</artifactId>
            <scope>test</scope>
        </dependency>

Test class
(With ability to set MongoDB version)

@ExtendWith(SpringExtension.class)
@DataMongoTest
class ModelRepoIntegrationTest {

    private static final String IP = "localhost";
    private static final int PORT = 28017; // <- set MongoDB port

    @TestConfiguration
    @Import(ModelRepo.class) // <- set the tested repository
    // @ComponentScan("com.example.repo") <- or package for several repositories
    static class Config {
        @Bean
        public IMongodConfig embeddedMongoConfiguration() throws IOException {
            return new MongodConfigBuilder()
                    .version(Version.V4_0_2) // <- set MongoDB version
                    .net(new Net(IP, PORT, Network.localhostIsIPv6()))
                    .build();
        }
    }

    @Autowired private ModelRepo repo; // <- tested repository
    @Autowired private MongoTemplate mongo; 

    @BeforeEach
    void setUp() { // clean db (slower) or collection (faster) before each test
        // mongo.getDb().drop();
        mongo.remove(new Query(), Model.class); 
    }

    @Test
    void create() {
        Model model = new Model() // <- tested entity
                          .setId(UUID.randomUUID())
                          .setNum(1)
                          .setText("text");
        Model actual = repo.create(model); // <- tested method of the repository
        List<Model> models = mongo.findAll(Model.class);
        assertThat(models).hasSize(1);
        Model expected = models.get(0);
        assertThat(actual).isEqualToComparingFieldByField(expected);
    }
}
Share:
13,162
Malakai
Author by

Malakai

Updated on June 22, 2022

Comments

  • Malakai
    Malakai almost 2 years

    I'm wondering, is there any example how to properly configure embedded MongoDB with Spring Boot?

    For example, this is how i configure H2 embedded database:

    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.context.annotation.Profile;
    import org.springframework.context.annotation.PropertySource;
    import org.springframework.core.env.Environment;
    import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
    import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
    import org.springframework.jndi.JndiObjectFactoryBean;
    
    import javax.sql.DataSource;
    
    
    @Configuration
    @PropertySource({"configs/datasource.properties"})
    public class DataSourceConfig {
    
        @Bean
        @Profile("test")
        public DataSource testDataSource() {
            return new EmbeddedDatabaseBuilder().setType(EmbeddedDatabaseType.H2).build();
        }
    }
    

    And this works well, but there is a problem. This approach doesnt provide configuration with MongoDB.

    Are there any workarounds?

    UPDATE 1:

    [ERROR] Failed to execute goal org.springframework.boot:spring-boot-maven-plugin:1.5.6.RELEASE:run (default-cli) on project XXX: An exception occurred while running. null: InvocationTargetException: Error creating bean with name 'mongoTemplate' defined in class path resource [com/reborn/XXX/config/DataSourceConfig .class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframewor k.data.mongodb.core.MongoTemplate]: Factory method 'mongoTemplate' threw exception; nested exception is java.lang.NoClassDefFoundError: de/flapdoodle/embed/mongo/distribu tion/IFeatureAwareVersion: de.flapdoodle.embed.mongo.distribution.IFeatureAwareVersion -> [Help 1]

    UPDATE 2:

    pom.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
    
        <groupId>com.reborn</groupId>
        <artifactId>xxx</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <packaging>jar</packaging>
    
        <name>xxx</name>
        <description>Demo project for Spring Boot</description>
    
        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>1.5.6.RELEASE</version>
            <relativePath/> <!-- lookup parent from repositories -->
        </parent>
    
        <properties>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
            <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
            <java.version>1.8</java.version>
        </properties>
    
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-data-mongodb</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
            </dependency>
            <dependency>
                <groupId>de.flapdoodle.embed</groupId>
                <artifactId>de.flapdoodle.embed.mongo</artifactId>
                <scope>test</scope>
            </dependency>
            <dependency>
                <groupId>cz.jirutka.spring</groupId>
                <artifactId>embedmongo-spring</artifactId>
                <version>1.3.1</version>
            </dependency>
        </dependencies>
    
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
            </plugins>
        </build>
    
    </project>
    

    DatasourceConfig:

    package com.reborn.xxx.config;
    
    import com.mongodb.MongoClient;
    import cz.jirutka.spring.embedmongo.EmbeddedMongoFactoryBean;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.data.mongodb.core.MongoTemplate;
    
    import java.io.IOException;
    
    @Configuration
    public class DataSourceConfig {
    
        @Bean
        public MongoTemplate mongoTemplate() throws IOException {
            EmbeddedMongoFactoryBean mongo = new EmbeddedMongoFactoryBean();
            mongo.setBindIp("localhost");
            MongoClient mongoClient = mongo.getObject();
            MongoTemplate mongoTemplate = new MongoTemplate(mongoClient, "abcd");
            return mongoTemplate;
        }
    
    }
    

    UPDATE 3:

    [ERROR] Failed to execute goal org.springframework.boot:spring-boot-maven-plugin:1.5.6.RELEASE:run (default-cli) on project starbucks-finder: An exception occurred while running. null: InvocationTargetException: Error creating bean with name 'mongoTemplate' defined in class path resource [com/reborn/xxx/config/DataSourceConfig .class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframewor k.data.mongodb.core.MongoTemplate]: Factory method 'mongoTemplate' threw exception; nested exception is java.lang.IllegalArgumentException: this version does not support 32Bit: PRODUCTION:Windows:B32 -> [Help 1]