使用 Junit 5 和 Micronaut 设置测试 MongoDBContainer

Posted

技术标签:

【中文标题】使用 Junit 5 和 Micronaut 设置测试 MongoDBContainer【英文标题】:Setting Test MongoDBContainer with Junit 5 and Micronaut 【发布时间】:2021-04-14 18:45:34 【问题描述】:

尝试使用 Junit 5 和 micronaut 设置 Test MongoDBContainer,而不是在使用 application.yml 配置的测试环境中盯着随机端口上的 MongoDB。

application.yml

micronaut:
  application:
    name: feteBirdProductConsumer

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

Junit 测试

@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);
        );
    

shouldSearchBasedOnTheName 方法的返回值来自 application.yml MongoDB 配置。

在测试环境中,我没有向 MongoDB 插入任何值,但该方法已从应用程序 MongoDB 返回值

我想我缺少 mongoDb 的配置,但不太确定如何设置

更新

@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
        );
    

例外

com.mongodb.MongoSocketReadException: Prematurely reached end of stream

【问题讨论】:

【参考方案1】:

您启动的测试容器绑定了一个随机端口,您需要手动将其提供给 Micronaut,两者之间没有自动集成。我不认为你可以使用@MicronautTest 来解决这个问题,因为它在容器初始化之前运行应用程序上下文。但是您仍然可以自己配置和启动上下文:

@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);
    

【讨论】:

是否需要设置client = context.getBean(MongoClient.class);因为 MongoClient 在另一个项目中,我无权从另一个项目访问该项目。或者只添加到 ApplicationContext 就足够了 对我不起作用。在Checking status of localhost:49185(当然是随机端口)之后我收到了:java.net.ConnectException: Connection refused: connect【参考方案2】:

Micronaut 需要从 MongoDBContainer 获取连接 URL,因此使用 MicronautTest 无法像使用特殊“tc”数据库 URL 的 SQL 容器那样工作。 JUnit 的答案类似于我对 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())
    

    ...

【讨论】:

以上是关于使用 Junit 5 和 Micronaut 设置测试 MongoDBContainer的主要内容,如果未能解决你的问题,请参考以下文章

使用 Micronaut 应用程序为 JUnit5 中的每个单元/集成测试运行一次 TestContainer

在 JUnit 5 完成所有类测试后,测试容器未从 docker 中删除

处理 bean 注册时出错 [io.micronaut.rabbitmq.intercept.RabbitMQConsumerAdvice]

为 mongodb 的 micronaut 设置测试容器

如何设置 Micronaut 上下文路径

Micronaut cli graphql 设置