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

Mar*_*rco 6 mongodb spring-boot testcontainers

我试图定义一个@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() }

  }

}
Run Code Online (Sandbox Code Playgroud)

问题似乎是该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();
  }
}
Run Code Online (Sandbox Code Playgroud)

我正在尝试实现同样的目标,但是在 Kotlin 中并使用 MongoDB。

知道可能是什么问题导致@DynamicPropertySource不被调用吗?

小智 10

这个解决方案对我有用。
方法@DynamicPropertySourceis inside 伴随对象(也添加 @JvmStatic)并添加org.testcontainers.junit.jupiter.Testcontainers到测试类上

import org.junit.jupiter.api.Test
import org.junit.jupiter.api.extension.ExtendWith
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.jdbc.DataSourceBuilder
import org.springframework.boot.test.context.TestConfiguration
import org.springframework.context.annotation.Bean
import org.springframework.test.context.ContextConfiguration
import org.springframework.test.context.DynamicPropertyRegistry
import org.springframework.test.context.DynamicPropertySource
import org.springframework.test.context.junit.jupiter.SpringExtension
import org.testcontainers.containers.PostgreSQLContainer
import org.testcontainers.junit.jupiter.Container
import org.testcontainers.junit.jupiter.Testcontainers
import javax.sql.DataSource


@ExtendWith(SpringExtension::class)
@Testcontainers
@TestConfiguration
@ContextConfiguration(classes = [PostgresqlTestContainersConfig::class])
class PostgresqlTestContainersConfig {

    @Autowired
    var dataSource: DataSource? = null

    @Test
    internal fun name() {
        dataSource!!.connection.close()
    }

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

    companion object {

        @JvmStatic
        @Container
        private val POSTGRES_CONTAINER: PostgreSQLContainer<*> = PostgreSQLContainer("postgres:9.6.12")
            .withDatabaseName("integration-tests-db")
            .withUsername("sa")
            .withPassword("sa")

        @JvmStatic
        @DynamicPropertySource
        fun postgreSQLProperties(registry: DynamicPropertyRegistry) {
            registry.add("db.url") { POSTGRES_CONTAINER.jdbcUrl }
            registry.add("db.user") { POSTGRES_CONTAINER.username }
            registry.add("db.password") { POSTGRES_CONTAINER.password }
        }
    }

}
Run Code Online (Sandbox Code Playgroud)


Kev*_*tek 3

@DynamicPropertySource是 Spring-Boot 上下文生命周期的一部分。由于您想以某种方式复制 Java 设置,因此不需要使用@DynamicPropertySource. 相反,您可以遵循Singleton Container Pattern,并将其复制到 Kotlin 中。

您可以将它们设置为系统属性,而不是在注册表中设置配置,Spring Autoconfig 将选择它:

    init { 
      MONGO_CONTAINER.start() 
      System.setProperty("spring.data.mongodb.uri", MONGO_CONTAINER.getReplicaSetUrl());
    }
Run Code Online (Sandbox Code Playgroud)