【问题标题】:Can't load a test-properties.yaml file with the @TestPropertySource with Spring Boot, JUnit5 and Kotlin无法使用 Spring Boot、JUnit5 和 Kotlin 加载带有 @TestPropertySource 的 test-properties.yaml 文件
【发布时间】:2020-03-07 11:01:53
【问题描述】:

我有一个类注入了位于src/main/resources 目录中的application.yaml 属性。 我编写了一个测试来断言这些属性是否按预期注入。 测试工作正常,但它使用的是来自src/main/resources 的application.yaml 文件。

我希望它使用来自src/test/resources 的test-application.yaml 文件来使用一些虚假值。

我在 Stackoverflow 上遵循了许多指南并阅读了许多问题,但无法使任何这些方法发挥作用。也许是因为我混淆了不同解决方案的注释或其他什么。

现状

我使用的是spring管理系统提供的spring版本

    id("io.spring.dependency-management") version "1.0.9.RELEASE"

编辑: 我还使用以下相关依赖项:

    testImplementation("org.springframework.boot:spring-boot-starter-test") {
        exclude(group = "org.junit.vintage", module = "junit-vintage-engine")
    }
    annotationProcessor("org.springframework.boot:spring-boot-configuration-processor")
    implementation("org.springframework.boot:spring-boot-starter-actuator")
    implementation("org.springframework.boot:spring-boot-starter-webflux")

属性文件src/main/resources/application.yaml:

controlroom:
  ftpConnections:
    foo-importer:
      host: ftp.stage.company.com
      port: 22
      user: foo-ftp
      password: password
    bar-importer:
      host: ftp.stage.company.com
      port: 22
      user: bar-ftp
      password: password

这是属性配置持有者类:

@Configuration
@ConfigurationProperties(prefix = "controlroom")
class FtpConnectionsProvider(
) {
    lateinit var ftpConnections: Map<String, Map<String, String>>
}

这是当前从main/resources/application.yaml注入属性的测试类:

@ExtendWith(SpringExtension::class)
@SpringBootTest
internal class FtpConnectionsProviderTest(
        @Autowired
        val ftpConnectionsProvider: FtpConnectionsProvider
) {
    @Test
    fun `should fill FtpConnectionsProvider with properties from yaml`() {
        assertThat(ftpConnectionsProvider.ftpConnections["foo-importer"]).containsAllEntriesOf(
                mapOf(
                        "host" to "ftp.stage.company.com",
                        "port" to "22",
                        "user" to "foo-ftp",
                        "password" to "password"
                ))
        assertThat(ftpConnectionsProvider.ftpConnections["bar-importer"]).containsAllEntriesOf(
                mapOf(
                        "host" to "ftp.stage.company.com",
                        "port" to "22",
                        "user" to "bar-ftp",
                        "password" to "password"
                ))
    }
}

如何使用 test-application.yaml ?

现在我想知道如何给测试提供只使用src/test/resources/test-application.yaml 的指令。

第一次尝试

@ExtendWith(SpringExtension::class)
@SpringBootTest
@TestPropertySource("classpath:test-application.yaml")
internal class FtpConnectionsProviderTest

结果:忽略它并继续使用src/main/resources/application.yaml

第二次尝试

人们说@TestPropertySource 无法读取.yaml 文件,因此我添加了@ContextConfiguration 注释,因为这是建议的修复。

@ExtendWith(SpringExtension::class)
@SpringBootTest
@TestPropertySource("classpath:test-application.yaml")
@ContextConfiguration(initializers=[ConfigFileApplicationContextInitializer::class])
internal class FtpConnectionsProviderTest

结果:忽略它并继续使用src/main/kotlin/resources/application.yaml

似乎没有任何效果。我不明白为什么这很重要,为什么找到解决方案如此复杂

【问题讨论】:

  • 你确定在你的类路径中有SnakeYaml吗?
  • @xerx593 是的。 imgur.com/a/dANSEdf
  • 不,不,抱歉,图片不是证据:您向我/我们展示了*.yaml 文件...我/我们需要:在您的spring-boot[-...]-starter / snake-yaml pom.xml/build.gradle.
  • @xerx593 请查看我对我使用的依赖项现状的编辑。我想再次提一下,.yaml 文件的注入确实有效,但我无法引用src/test/kolin/resources 目录中的那个
  • 谢谢! :)(排除 1 个“副作用”)

标签: spring spring-boot kotlin yaml


【解决方案1】:

您是否尝试在src/test/kotlin/resources 下放置application.yaml 文件?这应该可以在没有任何特殊配置/注释的情况下工作。

另外,如果您想在名为 testfoo 的 yaml 文件中拥有/覆盖某些属性,您可以将这些道具放在同一目录中的 application-testfoo.yaml 中,如果您激活 @987654325,将使用该文件@Spring 配置文件。

例子:

src/test/kotlin/resources/application.yaml:

controlroom:
  ftpConnections:
    foo-importer:
      host: ftp.stage.company.com
      port: 22
      user: foo-ftp
      password: password
    bar-importer:
      host: ftp.stage.company.com
      port: 22
      user: bar-ftp
      password: password

src/test/kotlin/resources/application-testfoo.yaml:

controlroom:
  ftpConnections:
    foo-importer:
      user: test-foo-ftp

如果您激活 testfoo 配置文件,controlroom.ftpConnections.foo-importer.user 将被覆盖。这就是你想要的吗?

或者,如果您只想替换几个生产属性值,作为更简单的解决方案:根本不要创建src/test/kotlin/resources/application.yaml。只需创建src/test/kotlin/resources/application-testfoo.yaml,它就会覆盖src/main/kotlin/resources/application.yaml 中的值(假设testfoo 配置文件处于活动状态)!无论如何,这在我的 applications.properties 中可以在 Java 中使用 - 我看不出它在 Kotlin 中的工作方式有何不同。

【讨论】:

  • 这不会出现在 target/test-classes 文件夹中名为 resources 的包中吗?
  • 这确实有效@Joel 问题是出于可读性原因我想拆分不同的test-foo-application.yaml
  • yaml 文件的可读性?如果是这样,您是否考虑过使用名为testfoo 的弹簧配置文件并将yaml 文件命名为application-testfoo.yaml(在同一测试目录下)?如果您使用该命名约定,Spring 应该会找到它。您可以拥有一个 application.yaml 文件,并且 application-testfoo.yaml 文件中的任何值都将覆盖它们。
【解决方案2】:

您无法使用 @TestPropertySource 加载 yaml 文件。

【讨论】:

  • 完全不可能?然后我怎样才能引入.yaml 属性文件用于测试目的
  • 最简单的方法是在测试文件夹中使用标准 application.yml 文件(我假设您正在使用 Maven),而不是不同的文件,对测试子集使用不同的配置文件,这需要进行不同的配置.. .
  • 这是今天 p.o.v 的一个很好的“总结”,但仍然是一个“永无止境的故事”:) ... stackoverflow.com/q/21271468/592355
猜你喜欢
  • 1970-01-01
  • 2019-03-20
  • 1970-01-01
  • 2020-09-26
  • 2018-03-24
  • 2017-05-28
  • 2020-12-04
  • 2019-06-17
  • 1970-01-01
相关资源
最近更新 更多