0

My question is similar to Populate a database with TestContainers in a SpringBoot integration test but instead I have a mongo db test container as follows:

@Container
private static MongoDBContainer mongoDBContainer = new MongoDBContainer(DockerImageName.parse("mongo:3.4.20")) 

I can use mongorepository.save() but that's not really feasible as there are multiple collections and I need populate several fields (and a bunch of them are nested fields). What are some other ways to achieve the same?

Diluted Dev
  • 45
  • 1
  • 9

3 Answers3

2

A way I've done it in the past when I need some initial data in the database is by adding an ApplicationContextInitializer that boots up the testcontainer and then run a mongorestore inside the container for loading a mongodump I prepared separately.

This way you can keep your dump folder in your test-resources folder. Ofcourse, if you have other files there be sure to use to the correct classpath resource path.

Hope this helps!

public class TestContainerInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {

    @SneakyThrows
    @Override
    public void initialize(ConfigurableApplicationContext context) {
        MongoDBContainer instance = MongoContainerSingleton.getInstance();
        instance.copyFileToContainer(
                MountableFile.forClasspathResource("/"), "/IT-dump");
        Container.ExecResult mongorestore = instance.execInContainer("mongorestore", "/IT-dump/dump/");
    }

    public static class MongoContainerSingleton {

        private static volatile MongoDBContainer instance = null;

        public static MongoDBContainer getInstance() {
            synchronized (MongoContainerSingleton.class) {
                if (instance == null) {
                    instance = new MongoDBContainer("mongo:4.2.11")
                            .withReuse(true);
                    instance.start();
                }
            }
            return instance;
        }
    }
}
0

I am not a MongoDB expert, but you should populate the database independent of the fact, that you are using Testcontainers to instrument it. So using the repository does seem right. You can also use a special repository in your test classes, to which you add methods that do bigger bootstrappings.

Also, consider stopping using the @Container annotation, which starts a container for every test class, this can lead to a lot of startup overhead. Generally, using the Singleton Container Pattern lead to much better test suite performance.

Kevin Wittek
  • 1,369
  • 9
  • 26
0

There is a liquibase mongodb project which can be used. You can take a look at this project. There is a db.changelog-master.json where the schema creation is defined as a first changelog (you can define more) and as you can see in the test just defined the container, set the spring.data.mongodb.uri and manually run the migration due to spring boot does not offer autoconfigure for liquibase mongodb extension.

 @Container
    private static final MongoDBContainer mongo = new MongoDBContainer("mongo:4.0.10");

    @Autowired
    private PersonRepository repository;

    @DynamicPropertySource
    static void mongoProperties(DynamicPropertyRegistry registry) {
        registry.add("spring.data.mongodb.uri", mongo::getConnectionString);
    }

    @Test
    void test() throws LiquibaseException {
        var database = (MongoLiquibaseDatabase) DatabaseFactory.getInstance().openDatabase(mongo.getReplicaSetUrl("test"), null, null, null, null);
        var liquibase = new Liquibase("db/changelog/db.changelog-master.json", new ClassLoaderResourceAccessor(), database);
        liquibase.update("");

        var books = this.repository.findAll();
        assertThat(books).hasSize(3);
    }

This sample project is based in spring boot too.

Also, check Initializing a fresh instance

Eddú Meléndez
  • 6,107
  • 1
  • 26
  • 35
  • I will check this out properly, thanks! But is there a way I can just create a collection in this container and insert json documents from some existing db I already have ? I am trying to do some compatibility work so my ideal scenario would to use some documents from some existing db and insert it in this container for testing purposes. – Diluted Dev Jul 20 '22 at 19:08
  • I have updated my answers pointing to the mongo docker documentation where you can use `/docker-entrypoint-initdb.d` to copy sh or js files – Eddú Meléndez Jul 20 '22 at 23:44