【问题标题】:how to override an application property programatically in Quarkus如何在 Quarkus 中以编程方式覆盖应用程序属性
【发布时间】:2020-11-09 14:34:47
【问题描述】:

我最近开始在我的 Quarkus Web 应用程序中使用 testcontantainers 进行单元/集成测试数据库操作。它工作正常,但我无法找到在 quarkus.datasource.url 应用程序属性中动态设置 MySQL 端口的方法。目前我正在使用已弃用的 withPortBindings 方法强制容器将暴露的 MySQL 端口绑定到端口 11111 但正确的方法是让 testcontainers 随机选择一个并覆盖 quarkus.datasource.url 属性.

我的单元测试类

    @Testcontainers
    @QuarkusTest
    public class UserServiceTest {
      @Container
      private static final MySQLContainer MY_SQL_CONTAINER = (MySQLContainer) new MySQLContainer()
          .withDatabaseName("userServiceDb")
          .withUsername("foo")
          .withPassword("bar")
          .withUrlParam("serverTimezone", "UTC")
          .withExposedPorts(3306)
          .withCreateContainerCmdModifier(cmd ->
              ((CreateContainerCmd) cmd).withHostName("localhost")
                .withPortBindings(new PortBinding(Ports.Binding.bindPort(11111), new ExposedPort(3306)))  // deprecated, let testcontainers pick random free port
          );
      
      @BeforeAll
      public static void setup() {
        // TODO: use the return value from MY_SQL_CONTAINER.getJdbcUrl()
        // to set %test.quarkus.datasource.url
        LOGGER.info(" ********************** jdbc url = {}", MY_SQL_CONTAINER.getJdbcUrl());
      }
      // snip...
    }

我的应用程序.properties:

%test.quarkus.datasource.url=jdbc:mysql://localhost:11111/userServiceDb?serverTimezone=UTC
%test.quarkus.datasource.driver=com.mysql.cj.jdbc.Driver
%test.quarkus.datasource.username=foo
%test.quarkus.datasource.password=bar
%test.quarkus.hibernate-orm.dialect=org.hibernate.dialect.MySQL8Dialect

Quarkus guide to configuring an app 描述了如何以编程方式读取应用程序属性:

String databaseName = ConfigProvider.getConfig().getValue("database.name", String.class);

但不是如何设置它。 This tutorial 在 Quarkus 中使用测试容器暗示它应该是可能的:

// 以下不应使用 - 函数已弃用,为了测试简单,您应该在运行时覆盖您的属性

解决方案: 正如接受的答案中所建议的,我不必在数据源属性中指定主机和端口。所以解决方法就是简单的替换application.properties中的两行:

%test.quarkus.datasource.url=jdbc:mysql://localhost:11111/userServiceDb
%test.quarkus.datasource.driver=com.mysql.cj.jdbc.Driver

%test.quarkus.datasource.url=jdbc:tc:mysql:///userServiceDb
%test.quarkus.datasource.driver=org.testcontainers.jdbc.ContainerDatabaseDriver

(并删除不必要的withExposedPortswithCreateContainerCmdModifier 方法调用)

【问题讨论】:

    标签: quarkus testcontainers


    【解决方案1】:

    请仔细阅读文档。端口可以​​省略。

    https://www.testcontainers.org/modules/databases/jdbc/

    【讨论】:

    • 谢谢,你说得对!我用针对我的案例的具体解决方案更新了我的问题。
    【解决方案2】:

    现在(quarkus 版本 19.03.12)可以简单一点。

    1. 定义启动容器并覆盖 JDBC 属性的测试组件
    
    import io.quarkus.test.common.QuarkusTestResourceLifecycleManager;
    import org.testcontainers.containers.PostgreSQLContainer;
    
    public class PostgresDatabaseResource implements QuarkusTestResourceLifecycleManager {
    
        public static final PostgreSQLContainer<?> DATABASE = new PostgreSQLContainer<>("postgres:10.5")
                .withDatabaseName("test_db")
                .withUsername("test_user")
                .withPassword("test_password")
                .withExposedPorts(5432);
    
        @Override
        public Map<String, String> start() {
            DATABASE.start();
            return Map.of(
                    "quarkus.datasource.jdbc.url", DATABASE.getJdbcUrl(),
                    "quarkus.datasource.db-kind", "postgresql",
                    "quarkus.datasource.username", DATABASE.getUsername(),
                    "quarkus.datasource.password", DATABASE.getPassword());
        }
    
        @Override
        public void stop() {
            DATABASE.stop();
        }
    }
    
    1. 在测试中使用它
    import io.quarkus.test.common.QuarkusTestResource;
    import io.quarkus.test.junit.QuarkusTest;
    import org.junit.jupiter.api.Test;
    
    import javax.ws.rs.core.MediaType;
    import java.util.UUID;
    import java.util.stream.Collectors;
    
    import static io.restassured.RestAssured.given;
    import static org.hamcrest.MatcherAssert.assertThat;
    import static org.hamcrest.Matchers.*;
    
    @QuarkusTest
    @QuarkusTestResource(PostgresDatabaseResource.class)
    public class MyControllerTest {
    
        @Test
        public void myAwesomeControllerTestWithDb() {
          // whatever you want to test here. Quarkus will use Container DB
          given().contentType(MediaType.APPLICATION_JSON).body(blaBla)
                    .when().post("/create-some-stuff").then()
                    .statusCode(200).and()
                    .extract()
                    .body()
                    .as(YourBean.class);
          
        }
    
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-05-19
      • 2019-02-20
      • 2020-07-28
      • 1970-01-01
      • 2022-11-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多