1

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
4

2 回答 2

3

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);
    }
于 2021-01-09T17:27:07.233 回答
0

Micronaut needs to get the connection URL from the MongoDBContainer, so using MicronautTest won't work the way it does with the SQL containers that use special "tc" database URLs. The JUnit answer is similar to what I have used for Spock,

@Testcontainers
class MongoControllerSpec extends Specification {

    @Shared
    MongoDBContainer mongo = new MongoDBContainer("mongo:4.1.1")
            .withExposedPorts(27017)

    @Shared
    @AutoCleanup
    EmbeddedServer embeddedServer

    @Shared
    @AutoCleanup
    RxHttpClient rxClient

    def setupSpec() {
        embeddedServer = ApplicationContext.run(EmbeddedServer,
                ['mongodb.uri': mongo.getReplicaSetUrl("micronaut")])
        rxClient = embeddedServer.applicationContext.createBean(RxHttpClient, embeddedServer.getURL())
    }

    ...
}
于 2021-01-11T18:50:31.713 回答