javajunitmicronauttestcontainersmicronaut-test

Setting Test MongoDBContainer with Junit 5 and Micronaut


Trying to setup Test MongoDBContainer with Junit 5 and micronaut, instead of staring the MongoDB at the random port on a test environment it is using the application.yml configuration.

application.yml

micronaut:
  application:
    name: feteBirdProductConsumer

mongodb:
  uri: "mongodb://${MONGO_HOST:localhost}:${MONGO_PORT:27017}"
  database: "FeteBird-Product"

Junit test

@MicronautTest
@Testcontainers
public class ProductListenerTest {
    private final IProductProducer iProductProducer;
    @Container
    private final MongoDBContainer mongoDBContainer = new MongoDBContainer(DockerImageName.parse("mongo:4.0.10"));

    public ProductListenerTest(IProductProducer iProductProducer) {
        this.iProductProducer = iProductProducer;
    }

    @BeforeEach
    @DisplayName("Mongo Db container starting")
    void mongoDbContainerStarting() {
        mongoDBContainer.start();
    }

    @Test
    @DisplayName("Check if Mongo db container is up")
    void checkIfMongoDbContainerIsUp() {
        Assertions.assertTrue(mongoDBContainer.isRunning());
    }


    @Test
    @DisplayName("Should search based on the name")
    void shouldSearchBasedOnTheName() {
        iProductProducer.findFreeText("string").subscribe(item -> {
            System.out.println(item);
        });
    }
}

On shouldSearchBasedOnTheName method the return value are from the application.yml MongoDB config.

In the test environment, I haven't inserted any value to the MongoDB, but that method has returning the value from the application MongoDB

I think I am missing the configuration for mongoDb, but quite not sure how to setup

Update

@TestInstance(TestInstance.Lifecycle.PER_CLASS)
public class ProductListenerTest implements TestPropertyProvider {
@Nonnull
    @Override
    public Map<String, String> getProperties() {
        mongoDBContainer.start();
        String address = mongoDBContainer.getHost();
        Integer port = mongoDBContainer.getFirstMappedPort();
        return CollectionUtils.mapOf(
                "MONGO_HOST", address,
                "MONGO_PORT", port
        );
    }
}

Exception

com.mongodb.MongoSocketReadException: Prematurely reached end of stream

Solution

  • The test container you're starting binds a random port that you need to manually feed to Micronaut, there is no automatic integration between the two. I don't think you can pull this off using @MicronautTest as it runs the application context before the container is even initialized. However you can still configure and start the context yourself:

    @Testcontainers
    public class ProductListenerTest {
        @Container
        private MongoDBContainer mongoDBContainer = 
                         new MongoDBContainer(DockerImageName.parse("mongo:4.0.10"));
        private ApplicationContext context;
        private MongoClient client;
    
        @BeforeEach
        void mongoDbContainerStarting() {
            mongoDBContainer.start();
            // Overwrite the mongodb.uri value from your configuration file
            context = ApplicationContext.run(
                          Map.of("mongodb.uri", mongoDBContainer.getReplicaSetUrl()));
            client = context.getBean(MongoClient.class);
        }