【问题标题】:Dynamically add property sources to SpringBootTest将属性源动态添加到 SpringBootTest
【发布时间】:2019-05-18 15:18:20
【问题描述】:

类似于Springboot unit test set @Configuration Properties dynamically,但上下文不同。

在我的情况下,我有一个 TestContainer 运行一个自定义 MySQL 数据库,该数据库预填充了大量数据(不使用 SQL 批量加载方法,因为数据是生产的匿名副本,并且通过 SQL 执行它可以启动容器的正常运行时间为 20 分钟 vs 2 分钟)。

到目前为止,我的测试看起来像这样

@RunWith(SpringRunner.class)
@SpringBootTest(
    classes = {
        Bootstrap.class
    }
)
public class ITFakeDB {
    @ClassRule
    public static final GenericContainer DB = new GenericContainer("devdb")
        .withExposedPorts(3306);
    @Autowired
    private DataSource dataSource;

    @Autowired
    private Users users;

    @Test
    public void testDatabaseIsUp() {
        assertTrue(DB.getMappedPort(3306) != 0);
    }

    @Test
    public void testUser() {
        Optional<User> user = users.findByLoginName("mimi");
        assertTrue(users.isPresent());
    }
}

我想做的是以某种方式将spring.datasource.url(或者在我的情况下为datasources.schema1.url,因为我做了routing datasource)设置为DB使用的那个

【问题讨论】:

  • DB 中获取 URL 并设置为变量的方法是什么?

标签: java spring spring-boot testing


【解决方案1】:

您可以使用 ContextConfigurationApplicationContextInitializer 在 Spring-boot 测试中手动覆盖该属性。

覆盖属性 - 定义一个静态内部类:

  static class Initializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {

    @Override
    public void initialize(ConfigurableApplicationContext configurableApplicationContext) {
      String url = "jdbc:mysql://" + DB.getContainerIpAddress() + ":" + DB.getMappedPort(3306) + "/my_db";

      TestPropertyValues
          .of("datasources.schema1.url=" + url)
          .applyTo(configurableApplicationContext.getEnvironment());
    }
  }

注意:我假设url 是从 IP 地址、端口和数据库名称派生的。您可以根据需要更改该部分,但核心思想仍然存在。

ApplicationContextInitializer 可用于在上下文刷新之前以编程方式初始化 Spring 上下文。现在,通过在测试类级别使用 ContextConfiguration 注释来连接上下文初始化器类:

@ContextConfiguration(initializers = Initializer.class)

文档:

ApplicationContextInitializer

ContextConfiguration

【讨论】:

  • 如果 datasources.schema1.url 已在 .properties 文件中定义,则此方法无效
【解决方案2】:

虽然前面的答案应该有效,但 Spring Framework 5.2.5(包含在 Spring Boot 2.2.6 中)已经针对这种情况引入了一个新的 @DynamicPropertySource 注释:

@DynamicPropertySource
static void initializeDatasource(DynamicPropertyRegistry registry) {
    String ip    = DB.getContainerIpAddress();
    Integer port = DB.getMappedPort(3306);
    String url   = String.format("jdbc:mysql://%s:%d/my_db", ip, port);
    
    registry.add("datasources.schema1.url", url);
}

查看详情:

【讨论】:

    猜你喜欢
    • 2019-04-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多