Search code examples
spring-bootspring-data-mongodbembedded-mongodb

Embedded Mongo migration from spring boot 2.7 to 3.1.1


I was using de.flapdoodle.embed:de.flapdoodle.embed.mongo:3.5.0

I have created EmbeddedMongoServer class, where I am importing MongoProcess MongodStarter Defaults MongodConfig RuntimeConfig MongodExecutable

However, I want to upgrade my internal mongo library from springboot 2.7 to 3.1.1 and when I replaced flapdoodle to flapdoodle.embed.mongo.spring30x:4.5.2 It can not find the above mentioned classes/interfaces. How can I successfully migrate ?

I am trying with flapdoodle.embed.mongo.spring30x:4.5.2


Solution

  • I just ran into this today. You didn't mention it, but just in case, you need both flapdoodle embed mongo and the spring30x test libraries.

    Here's what I did for mine.

    Assuming you are using:

    Java 17
    spring-web: 3.1.0
    spring-data-mongodb: 3.1.0
    
    

    Test Libs

    testImplementation 'de.flapdoodle.embed:de.flapdoodle.embed.mongo:4.7.1'
    testImplementation 'de.flapdoodle.embed:de.flapdoodle.embed.mongo.spring30x:4.7.0'
    testImplementation('org.springframework.boot:spring-boot-starter-test') {
            exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
    }
    

    test/resources/application-test.yaml

    de:
      flapdoodle:
        mongodb:
          embedded:
            version: 4.4.18
            storage:
              repl-set-name: rs0
    spring:
      data:
        mongodb:
          database: test
    

    And based on their samples:

    import me.com.MyApplication;
    import org.junit.jupiter.api.Assertions;
    import org.junit.jupiter.api.Test;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
    import org.springframework.boot.test.autoconfigure.data.mongo.AutoConfigureDataMongo;
    import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.data.mongodb.core.MongoTemplate;
    import org.springframework.test.context.ActiveProfiles;
    
    import java.util.ArrayList;
    
    import static org.assertj.core.api.Assertions.assertThat;
    
    
    
    @ActiveProfiles("test")
    @SpringBootTest(
            classes = MyApplication.class,
            webEnvironment = SpringBootTest.WebEnvironment.MOCK
    )
    public class ExampleIT {
        @Test
        void example(@Autowired final MongoTemplate mongoTemplate) {
            Assertions.assertNotNull(mongoTemplate.getDb());
            ArrayList<String> collectionNames = mongoTemplate.getDb()
              .listCollectionNames()
              .into(new ArrayList<>());
            assertThat(collectionNames).isNotEmpty();
        }
    }
    

    or a sliced test

    import me.com.MyApplication;
    import org.junit.jupiter.api.Assertions;
    import org.junit.jupiter.api.Test;
    import org.junit.jupiter.api.extension.ExtendWith;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.autoconfigure.data.mongo.DataMongoTest;
    import org.springframework.data.mongodb.core.MongoTemplate;
    import org.springframework.test.context.ActiveProfiles;
    import org.springframework.test.context.ContextConfiguration;
    import org.springframework.test.context.junit.jupiter.SpringExtension;
    
    import java.util.ArrayList;
    
    import static org.assertj.core.api.Assertions.assertThat;
    
    @DataMongoTest()
    @ActiveProfiles("test")
    @ExtendWith(SpringExtension.class)
    @ContextConfiguration(classes = MyApplication.class)
    public class ExampleIT {
        @Test
        void example(@Autowired final MongoTemplate mongoTemplate) {
            Assertions.assertNotNull(mongoTemplate.getDb());
            ArrayList<String> collectionNames = mongoTemplate.getDb()
              .listCollectionNames()
              .into(new ArrayList<>());
            assertThat(collectionNames).isEmpty();
        }
    }
    
    

    Notes:

    • These flapdoodle properties are setup for my production MongoDB version which is also setup as a replica set.
    • I use profiles to setup different Mongo configurations; local, vs AWS, vs test. If your setup is different, you might not need the @ActiveProfiles
    • I am also using Mongock for migrations and it requires journaling to be turned on. Since replica sets enable this by default, I didn't need to do anything else. However, if you aren't in RS mode, look at customizing your command options. Something like this might get you there.
    import de.flapdoodle.embed.mongo.commands.MongodArguments;
    
    @Bean
    MongodArguments mongodArguments() {
        return MongodArguments.builder().useNoJournal(false).build();
    }