覆盖Junit Test中的默认Spring-Boot application.properties设置

FrV*_*aBe 174 java unit-testing spring-boot

我有一个Spring-Boot应用程序,其中默认属性设置在application.properties类路径中的文件中(src/main/resources/application.properties).

我想在我的JUnit测试中覆盖一些默认设置,其中包含在test.properties文件中声明的属性(src/test/resources/test.properties)

我通常会为我的Junit测试提供专用的Config类,例如

package foo.bar.test;

import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;

@Configuration
@Import(CoreConfig.class)
@EnableAutoConfiguration
public class TestConfig {

}
Run Code Online (Sandbox Code Playgroud)

我首先想到@PropertySource("classpath:test.properties")在TestConfig类中使用可以解决这个问题,但这些属性不会覆盖application.properties设置(请参阅Spring-Boot参考文档 - 23.外部化配置).

然后我尝试-Dspring.config.location=classpath:test.properties在调用测试时使用.这很成功 - 但我不想为每次测试执行设置此系统属性.因此我把它放在代码中

@Configuration
@Import(CoreConfig.class)
@EnableAutoConfiguration
public class TestConfig {

  static {
    System.setProperty("spring.config.location", "classpath:test.properties");
  }

}
Run Code Online (Sandbox Code Playgroud)

不幸的是,再次没有成功.

必须有一个关于如何application.properties在JUnit测试中覆盖设置的简单解决方案test.properties,我必须忽略它.

And*_*son 267

您可以使用@TestPropertySource覆盖值application.properties.从它的javadoc:

测试属性源可用于有选择地覆盖系统和应用程序属性源中定义的属性

例如:

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = ExampleApplication.class)
@TestPropertySource(locations="classpath:test.properties")
public class ExampleApplicationTests {

}
Run Code Online (Sandbox Code Playgroud)

  • 还要注意`@TestPropertySource`可以接受一个`properties`参数来覆盖一些内联属性,比如`@TestPropertySource(properties ="myConf.myProp = valueInTest")`,如果你不想要一个完全有用的话全新的物业档案. (53认同)
  • 注意,`@ SpringApplicationConfiguration`已被弃用,你应该使用`@SpringBootTest` (7认同)
  • 而已。谢谢。不幸的是,当在ExampleApplication.class上使用它时,它不起作用,因此我必须在每个测试类上对其进行设置。那正确吗? (2认同)
  • 它必须位于测试类层次结构中的某个位置,即您可以使用公共超类在多个不同的测试类中配置它。 (2认同)
  • 您可以在数组中指定多个文件,也可以在文件系统上指定文件(但请记住它们可能无法在CI服务器上运行):`@TestPropertySource(locations = {"file:C:/ dev/...","类路径:test.properties"})` (2认同)
  • 如果文件“src/test/resources/application-test.properties”可以用于单元测试,那就太好了。 (2认同)
  • @Stefan 如果您使 `test` 配置文件处于活动状态,则可以使用它。 (2认同)

Rob*_*nch 62

您还可以使用元注释来外部化配置.例如:

@RunWith(SpringJUnit4ClassRunner.class)
@DefaultTestAnnotations
public class ExampleApplicationTests { 
   ...
}

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@SpringApplicationConfiguration(classes = ExampleApplication.class)
@TestPropertySource(locations="classpath:test.properties")
public @interface DefaultTestAnnotations { }
Run Code Online (Sandbox Code Playgroud)


Moh*_*ish 58

src/test/resources/application.properties如果使用以下注释,Spring Boot会自动加载

@RunWith(SpringRunner.class)
@SpringBootTest
Run Code Online (Sandbox Code Playgroud)

因此,重命名test.propertiesapplication.properties使用自动配置.

如果**只需要加载属性文件(进入环境),您也可以使用下面的,因为解释这里

@RunWith(SpringRunner.class)
@ContextConfiguration(initializers = ConfigFileApplicationContextInitializer.class) 
Run Code Online (Sandbox Code Playgroud)

[ 更新:覆盖某些测试属性 ]

  1. 添加src/main/resources/application-test.properties.
  2. 使用注释测试类@ActiveProfiles("test").

此负载application.properties然后 application-test.properties属性到用于测试案例应用背景下,作为每定义的规则在这里.

演示 - https://github.com/mohnish82/so​​-spring-boot-testprops

  • 如果到目前为止您不使用配置文件,则不需要专用的"测试"配置文件.只需将您的测试属性命名为"application-default.properties",它们就会被考虑,因为您自动运行"默认"配置文件(如果没有声明任何其他配置文件). (9认同)
  • 春天不给予保证.构建工具将在测试期间使用测试资源来支持主要资源.但是在测试application.properties的情况下,将忽略主application.properties.这不是我想要的,因为主要的一个包含几个有用的默认值,我只需要在测试期间覆盖其中一些(我不想在测试部分复制整个文件).见[这里](https://twitter.com/snicoll/status/887224501871751168). (7认同)
  • 你是对的,在测试阶段只加载`src/test/resources/application.properties`中定义的属性,忽略`src/main/resources/application.properties`. (5认同)
  • 不确定在类路径上有两个 `application.properties` 文件是否是个好主意(一个在 `src/main/resources` 中,一个在 `src/test/resources` 中)。谁保证两个都被拿走,哪一个先拿走? (4认同)
  • @FrVaBe Spring可以保证!主配置文件属性始终会加载。然后,在测试阶段,将加载测试属性,添加/覆盖新的/现有的属性。如果您不喜欢保留两个同名文件,则可以在src / main / resources中添加application-test.properties,并在测试用例中将test指定为活动配置文件。 (3认同)

Nim*_*ari 12

如果使用@SpringBootTest注释,则另一种适合覆盖测试中的一些属性的方法:

@SpringBootTest(properties = {"propA=valueA", "propB=valueB"})
Run Code Online (Sandbox Code Playgroud)

  • `SpringBootTest` 是否加载 application.properties 文件? (3认同)

jum*_*key 11

如果你像我和你有相同application.propertiessrc/main/resourcessrc/test/resources,和你想知道为什么application.properties在你的测试文件夹中未覆盖application.properties在你的主要资源,阅读...

简单解释:

如果你有application.propertiessrc/main/resources和相同application.propertiessrc/test/resources,其application.properties被捞起,取决于你如何运行测试。文件夹结构 src/main/resourcessrc/test/resources, 是 Maven 架构约定,因此如果您像mvnw test甚至一样运行测试gradlew testapplication.propertiesinsrc/test/resources将被选中,因为测试类路径将在类路径之前。但是,如果您像Run as JUnit Test在 Eclipse/STS 中一样运行测试,则application.propertiesinsrc/main/resources将被选中,因为类路径在测试类路径之前。

您可以通过打开菜单栏 来查看Run > Run Configurations > JUnit > *your_run_configuration* > Click on "Show Command Line"

你会看到这样的事情:

XXXbin\javaw.exe -ea -Dfile.encoding=UTF-8 -classpath
XXX\workspace-spring-tool-suite-4-4.5.1.RELEASE\project_name\bin\main;
XXX\workspace-spring-tool-suite-4-4.5.1.RELEASE\project_name\bin\test;

您是否看到classpath xxx\main首先出现,然后是xxx\test?是的,这都是关于类路径的:-)

旁注:请注意,在启动配置中覆盖的属性(例如在 Spring Tool Suite IDE 中)优先于 application.properties。

更改顺序:

现在,一切都可以在 Spring 中进行配置。您可以更改构建类路径,以便xxx\test首先出现,然后是xxx\main

只需转到Project > Properties > Java Build Path > Order and Export,通过将任何测试文件夹放在第一位来更改构建类路径顺序,例如:

在此处输入图片说明

就是这样!

更好的解决方案

但是,在测试时,更好的解决方案是激活src/test/resources/application-{profile}.propertiesprofile可以测试的位置),例如以下内容src/main/resources/application.properties

spring.profiles.active=测试

这更简洁,让您可以完全控制在做什么时要激活的配置文件。

  • 嘿@elonderin,感谢您的评论。如果有一些通用的配置,我会将它们插入“application.properties”中。此后,如果我在“local”上开发并执行“test”,“spring.profiles.active=local, test”。如果我处于预生产状态,则它变为“spring.profiles.active=预生产,测试”。这是你想要的吗? (2认同)
  • 这应该是公认的答案。显然,test/application.properties 不会覆盖 main/application.properties。 (2认同)

Fel*_*ati 11

如果您使用 Spring 5.2.5 和 Spring Boot 2.2.6 并且只想覆盖几个属性而不是整个文件。您可以使用新的注释:@DynamicPropertySource

@SpringBootTest
@Testcontainers
class ExampleIntegrationTests {

    @Container
    static Neo4jContainer<?> neo4j = new Neo4jContainer<>();

    @DynamicPropertySource
    static void neo4jProperties(DynamicPropertyRegistry registry) {
        registry.add("spring.data.neo4j.uri", neo4j::getBoltUrl);
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 这应该是最重要的答案。覆盖测试中的属性通常需要动态值,并且仅切换到另一个属性文件(因为其他答案不会削减它)。注意:此功能不需要“@Testcontainers”注释。 (2认同)

elo*_*rin 7

TLDR:

因此,我要做的是拥有标准src/main/resources/application.properties,并且在src/test/resources/application-default.properties其中我覆盖了所有测试的某些设置。

整个故事

我遇到了同样的问题,到目前为止也没有使用配置文件。现在必须这样做并记得声明配置文件似乎很麻烦-这很容易被忘记。

诀窍是,利用特定application-<profile>.properties于配置文件的配置来覆盖常规配置文件中的设置。参见https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html#boot-features-external-config-profile-specific-properties