@DynamicPropertySource未被调用(Kotlin、Spring Boot和TestContainers)

osh3o9ms  于 2022-10-22  发布在  Kotlin
关注(0)|答案(2)|浏览(183)

我正在尝试定义一个在所有集成测试之前执行一次的@TestConfiguration类,以便在Spring Boot项目中运行Kotlin中的MongoDB TestContainer。
以下是代码:

import org.springframework.boot.test.context.TestConfiguration
import org.springframework.test.context.DynamicPropertyRegistry
import org.springframework.test.context.DynamicPropertySource
import org.testcontainers.containers.MongoDBContainer
import org.testcontainers.utility.DockerImageName

@TestConfiguration
class TestContainerMongoConfig {

  companion object {

    @JvmStatic
    private val MONGO_CONTAINER: MongoDBContainer = MongoDBContainer(DockerImageName.parse("mongo").withTag("latest")).withReuse(true)

    @JvmStatic
    @DynamicPropertySource
    private fun emulatorProperties(registry: DynamicPropertyRegistry) {
      registry.add("spring.data.mongodb.uri", MONGO_CONTAINER::getReplicaSetUrl)
    }

    init { MONGO_CONTAINER.start() }

  }

}

问题似乎是没有调用emulatorProperties方法。常规流程应该是启动容器,然后设置属性。第一步会发生,第二步不会。
我知道有一个替代方案,我可以在每个功能测试类中进行此配置,但我不喜欢它,因为它会向测试类添加不需要的噪音。
例如,对于使用Postgres的Java项目,我设法使其与以下代码一起工作:

import javax.sql.DataSource;

import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.context.annotation.Bean;
import org.testcontainers.containers.PostgreSQLContainer;
import org.testcontainers.utility.DockerImageName;

@TestConfiguration
public class PostgresqlTestContainersConfig {

  static final PostgreSQLContainer POSTGRES_CONTAINER;
  private final static DockerImageName IMAGE = DockerImageName.parse("postgres").withTag("latest");

  static {
    POSTGRES_CONTAINER = new PostgreSQLContainer(IMAGE);
    POSTGRES_CONTAINER.start();
  }

  @Bean
  DataSource dataSource() {
    return DataSourceBuilder.create()
        .username(POSTGRES_CONTAINER.getUsername())
        .password(POSTGRES_CONTAINER.getPassword())
        .driverClassName(POSTGRES_CONTAINER.getDriverClassName())
        .url(POSTGRES_CONTAINER.getJdbcUrl())
        .build();
  }
}

我正在尝试实现相同的功能,但使用的是Kotlin和MongoDB。
你知道是什么原因导致@DynamicPropertySource没有被调用吗?

mfpqipee

mfpqipee1#

@DynamicPropertySource是Spring-Boot上下文生命周期的一部分。由于您希望以某种方式复制Java设置,因此不需要使用@DynamicPropertySource。相反,您可以遵循Singleton Container模式,并将其复制到Kotlin中。
您可以将它们设置为系统属性,而不是在注册表上设置配置,而Spring Autoconfig将获取它:

init { 
      MONGO_CONTAINER.start() 
      System.setProperty("spring.data.mongodb.uri", MONGO_CONTAINER.getReplicaSetUrl());
    }
332nm8kg

332nm8kg2#

我能够通过以下方式解决Groovy中的类似问题:
在测试类中直接使用@DynamicPropetySource注解静态方法(可能它也可以在超类中工作)。
但我不想将代码复制到每个需要MongoDB的测试类中。我使用ApplicationContexInitializer解决了该问题
该示例是用groovy编写的

class MongoTestContainer implements ApplicationContextInitializer<ConfigurableApplicationContext>{

  static final MongoDBContainer mongoDBContainer = new MongoDBContainer(DockerImageName.parse("mongo:6.0.2"))

  @Override
  void initialize(ConfigurableApplicationContext applicationContext) {
    mongoDBContainer.start()
    def testValues = TestPropertyValues.of("spring.data.mongodb.uri="+ mongoDBContainer.getReplicaSetUrl())
    testValues.applyTo(applicationContext.getEnvironment())
  }
}

为了完成它,在测试类中,您只需要添加@ContextConfiguration(initializers = MongoTestContainer)来激活测试的上下文初始化器。
为此,您还可以创建自定义注解,将@DataMongoTest与前面的注解结合起来。

相关问题