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


198

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

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

我通常为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 {

}

我首先认为@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");
  }

}

不幸的是再次失败。

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


如果只需要配置一些属性,则可以使用新的@DynamicPropertySource批注。stackoverflow.com/a/60941845/8650621
Felipe Desiderati

Answers:


293

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

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

例如:

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

}

2
而已。谢谢。不幸的是,当在ExampleApplication.class上使用它时,它不起作用,因此我必须在每个测试类上对其进行设置。那正确吗?
FrVaBe 2015年

1
它必须放在测试类的层次结构中,即可以使用一个公共的超类在多个不同的测试类中对其进行配置。
Andy Wilkinson

64
还要注意,@TestPropertySource可以接受一个properties参数以内联一些属性,例如@TestPropertySource(properties = "myConf.myProp=valueInTest"),这在您不希望使用全新的属性文件的情况下很有用。
dyng 2016年

2
您可以在一个数组中指定多个文件,也可以在文件系统上指定文件(但请记住,它们可能无法在CI服务器上使用):@TestPropertySource(locations={"file:C:/dev/...","classpath:test.properties"})
Adam

8
请注意,该@SpringApplicationConfiguration功能已被弃用,您应该使用@SpringBootTest
mrkernelpanic

74

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

@RunWith(SpringRunner.class)
@SpringBootTest

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

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

@RunWith(SpringRunner.class)
@ContextConfiguration(initializers = ConfigFileApplicationContextInitializer.class) 

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

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

根据此处定义的规则,这会加载测试属性application.properties然后将其 application-test.properties放入测试案例的应用程序上下文中。

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


1
不知道application.properties在类路径上有两个文件(一进src/main/resources一出src/test/resources)是否是一个好主意。谁能保证同时采取这两项措施?
FrVaBe

3
@FrVaBe Spring可以保证!主概要文件属性始终会加载。然后在测试阶段,将加载测试属性,添加/覆盖新的/现有的属性。如果你不喜欢保持两个文件同名,那么你可以添加application-test.propertiessrc/main/resources,并指定test作为测试用例活动的配置文件。
Mohnish

7
春天不提供保证。在测试期间,构建工具将使用测试资源,而使用主要资源。但是在测试application.properties的情况下,主application.properties将被忽略。那不是我想要的,因为主要值包含几个有用的默认值,并且我只需要在测试期间覆盖其中的一些默认值即可(并且我不想在测试部分中复制整个文件)。看这里
FrVaBe

6
您是正确的,src/test/resources/application.properties在测试阶段仅加载中定义的属性,将src/main/resources/application.properties被忽略。
Mohnish

11
如果到目前为止您尚未使用配置文件,则不需要专用的“测试”配置文件。只需命名测试属性即可application-default.properties,因为您将自动运行“默认”配置文件(如果未声明其他任何配置文件),则将考虑它们。
FrVaBe

65

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

@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 { }

21

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

@SpringBootTest(properties = {"propA=valueA", "propB=valueB"})

1
SpringBootTest加载application.properties文件?
TuGordoBello

8

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


3

简单说明:

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

如果您application.propertiessrc/main/resourcesapplication.properties之下src/test/resourcesapplication.properties被捞起,取决于你如何运行测试。文件夹结构 src/main/resourcessrc/test/resources,是Maven的体系结构约定,因此,如果您像mvnw test甚至运行测试gradlew test,则application.propertiesin src/test/resources将会被拾取,因为测试类路径将在类路径之前。但是,如果您像Run as JUnit Test在Elipse / STS中那样运行测试,则application.propertiesin src/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;

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

干杯


1
I just configured min as the following :

spring.h2.console.enabled=true
spring.h2.console.path=/h2-console


# changing the name of my data base for testing
spring.datasource.url= jdbc:h2:mem:mockedDB
spring.datasource.username=sa
spring.datasource.password=sa



# in testing i don`t need to know the port

#Feature that determines what happens when no accessors are found for a type
#(and there are no annotations to indicate it is meant to be serialized).
spring.jackson.serialization.FAIL_ON_EMPTY_BEANS=false`enter code here`

1

如果您使用的是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);
    }
}

0

否则,我们可以更改默认属性配置器名称,设置属性spring.config.name=test,然后使用该单独的test.properties自动配置src/test/test.properties我们的本机实例的类路径资源 org.springframework.boot.SpringApplication,而忽略应用程序属性;

好处:自动配置测试;

缺点:在CI层公开“ spring.config.name”属性

参考:http : //docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.html

spring.config.name =应用程序#配置文件名


5
application.properties对我来说,忽略不是一个选择,因为我只想覆盖测试中的某些原始配置值。
FrVaBe

我一直在寻找一种方法来完成一个不加载src / main / resources / application.properties的测试,就是这样。创建一个文件:src / test / resources / empty.properties并将注释添加到应该忽略主要属性的测试中。@TestPropertySource(properties =“ spring.config.name = empty”)
rvertigo

如何为每种junit测试方法设置特定的属性值?
尼古拉斯

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.