【问题标题】:How to setup local dev environment properties of Spring Boot based on docker compose with testcontainers?如何基于 docker compose 和 testcontainers 设置 Spring Boot 的本地开发环境属性?
【发布时间】:2021-07-09 15:46:28
【问题描述】:

我正在开发一个具有许多依赖项的服务,例如 Redis、PubSub、S3、ServiceC 和 ServiceD。当我在开发中达到终点时,例如/data/4,向ServiceC发起http请求。

为了让它工作,必须运行模拟 ServiceC 的东西。就我而言,它是wiremock(因为我不能直接运行ServiceC,因为它也有很多依赖项)。所有这些 MockService 都在一个 docker-compose-dev 文件中。

现在我的问题是:如何使用 testcontainers 运行 docker-compose,获取分配的端口,并将正确的属性设置为 WebClient 具有正确的模拟 url + 端口?

在 spring boot 启动之前我可以使用什么生命周期钩子来运行,并且还可以配置属性?

一个缺点是在开发模式下会增加启动时间,但我无法在 docker compose 文件中分配固定端口,因为它们可能会在开发人员的机器上使用。因此,为 localhost 上的服务 url 提供默认的 url 是没有意义的。

【问题讨论】:

    标签: spring-boot testcontainers


    【解决方案1】:

    Testcontainers 支持使用 DockerComposeContainer 类开箱即用地启动 Docker Compose。在创建此类的实例时,您必须公开所有容器:

    @Testcontainers
    public class DockerComposeTest {
    
      @Container
      public static DockerComposeContainer<?> environment =
        new DockerComposeContainer<>(new File("docker-compose.yml"))
          .withExposedService("database_1", 5432, Wait.forListeningPort())
          .withExposedService("keycloak_1", 8080,
            Wait.forHttp("/auth").forStatusCode(200)
            .withStartupTimeout(Duration.ofSeconds(30)));
    
    
      @Test
      void dockerComposeTest() {
        System.out.println(environment.getServicePort("database_1", 5432));
        System.out.println(environment.getServicePort("keycloak_1", 8080));
      }
    
    }
    

    上面的示例将 PostgreSQL 数据库和 Keycloak 映射到您机器上的随机临时端口。等待检查通过后,您的测试将立即运行,您可以使用 .getServicePort() 访问实际端口。

    WebClient 配置的一个可能解决方案是使用ApplicationContextInitializer,因为您必须在容器启动之前以某种方式定义 Spring Boot 属性:

    public class PropertyInitializer
      implements ApplicationContextInitializer<ConfigurableApplicationContext> {
     
      @Override
      public void initialize(ConfigurableApplicationContext configurableApplicationContext) {
     
        // static access to environment variable of the test
        TestPropertyValues
          .of("your_web_client_base_url=http://localhost:" + environment.getServicePort("serviceC", 8080) + "/api")
          .applyTo(configurableApplicationContext);
      }
    }
    

    然后您可以使用以下方法为您的集成测试注册初始化程序:

    @Testcontainers
    @ContextConfiguration(initializers = {PropertyInitializer.class})
    class DockerComposeTest {
    }
    

    作为替代方案,您也可以尝试仅模拟与外部服务with WireMock 的所有 HTTP 通信。

    【讨论】:

      猜你喜欢
      • 2020-05-03
      • 1970-01-01
      • 1970-01-01
      • 2018-11-28
      • 2021-01-21
      • 2020-02-09
      • 2017-02-12
      • 2014-10-28
      • 1970-01-01
      相关资源
      最近更新 更多