在 springboottest 中从默认 applicaton.yml 设置 testcontainer 属性的更好方法

Posted

技术标签:

【中文标题】在 springboottest 中从默认 applicaton.yml 设置 testcontainer 属性的更好方法【英文标题】:Better way to set testcontainer properties from default applicaton.yml in springboottest 【发布时间】:2020-11-23 10:36:04 【问题描述】:

我在 springboottest 中使用 posgresql testcontainer。由于我有多个涉及此测试容器的测试,因此我使用了静态测试容器,它将为 1 个 junit 类的所有测试调用一次,并在所有测试执行后关闭。

这是我使用 ParameterResolver 实现的,BeforeEachCallback。

这种方法的问题是,默认 application.yml 中配置的 jdbc-url、db name、host、port 等数据源元数据没有直接用于 testcontainer 属性,而是我对这些值进行了硬编码,因为 springboot 属性在那个时候不可用时间。

有没有更好的方法可以让我使用具有 BeforeEachCallback 功能的静态测试容器,其值是从默认的 application.yml 中获取的?

@SpringBootTest
class SampleTest extends TestContainerBase 

    @Test
    void test1() 
        //some code
    



@ExtendWith(ContainerExtension.class)
@ResourceLock(Environment.ID)
public abstract class TestContainerBase 

    protected static String jdbcUrl;
    protected static String username;
    protected static String password;

    @BeforeAll
    static void prepareContainerEnvironment(Environment env) 
        jdbcUrl = env.getJdbcUrl();
        username = env.getUsername();
        password = env.getPassword();
    

    @DynamicPropertySource
    static void dynamicPropertySource(DynamicPropertyRegistry registry) 

        registry.add("spring.datasource-.jdbc-url", () -> jdbcUrl);
        registry.add("spring.datasource-.username", () -> username);
        registry.add("spring.datasource-.password", () -> password);
        registry.add("spring.datasource-.driver-class-name", () -> "org.postgresql.Driver");
    



public class ContainerExtension implements ParameterResolver, BeforeEachCallback 
    
    // overridden supportsParameter and resolveParameter

我希望从 application.yml 中读取 myDB 、 sa 、 sa 。如何在此类中获取 application.yml 值?由于尚未加载 springboot 上下文,因此我想不出任何替代方法来获取这些值。

public class ContainerResource extends Environment 

    @Container
    protected static PostgreSQLContainer postgreSQLContainer =
            new PostgreSQLContainer("artifactory.devtools.syd.c1.macquarie.com:9996/postgres:11")
                    .withDatabaseName("myDB")
                    .withUsername("username")
                    .withPassword("password");
    
    ContainerEnvironmentResource() 
        postgreSQLContainer.start();
        this.setJdbcUrl(postgreSQLContainer.getJdbcUrl());
        this.setUsername(postgreSQLContainer.getUsername());
        this.setPassword(postgreSQLContainer.getPassword());
    

【问题讨论】:

也许我误解了,但不会在某些常量字段中保留“myDB , sa , sa” 并将这些常量导入您需要它们不起作用的任何地方?将它们保存在 .yml 中并不能解决问题,但它们不会被复制。 @VitalyChura 我的主要意图是它应该从 application.yml 中挑选,我不应该将它保留在其他任何地方,以便将来如果任何其他开发人员对此进行工作,不会有任何混淆跨度> 【参考方案1】:

现在似乎有一个专门的项目来集成 Testcontainers 和 Spring-Boot。据我了解文档应该对代码透明,因为一切都是使用 Spring 魔术完成的。

https://github.com/Playtika/testcontainers-spring-boot

【讨论】:

以上是关于在 springboottest 中从默认 applicaton.yml 设置 testcontainer 属性的更好方法的主要内容,如果未能解决你的问题,请参考以下文章

Spring Boot 2.x 实践记:@SpringBootTest

Spring Boot 2.x 实践记:@SpringBootTest

Spring Boot 2.x 实践记:@SpringBootTest

SpringBootTest - 如何在测试级别断言上下文不加载和更改属性?

SpringBootTest 和Testng组成测试套件

在 Swift 中从 App 启动 App Store