集成测试的 Spring-boot 默认配置文件

Spring-boot 利用了 弹簧型材,它允许对不同的环境进行单独的配置。 使用此特性的一种方法是配置测试数据库以供集成测试使用。 但是,我想知道: 是否有必要创建我自己的配置文件‘ test’并在每个测试文件中显式激活这个配置文件? 现在,我用下面的方法来做:

  1. src/main/resources中创建 application-test. properties

  2. 在那里编写特定于测试的配置(目前只是数据库名称)

  3. 在每个测试文件中,包括:

    @ActiveProfiles("test")
    

有没有更聪明/更简洁的方法? 例如,默认的测试配置文件?

编辑1: 这个问题与 Spring-Boot1.4.1有关

187678 次浏览

据我所知,没有什么能直接回应你的要求——但我可以提出一个可能有帮助的建议:

您可以使用自己的测试注释,即包含 @SpringBootTest@ActiveProfiles("test")元注释。因此,您仍然需要专用的概要文件,但是要避免在所有测试中分散概要文件定义。

该注释将默认为配置文件 test,您可以使用元注释覆盖该配置文件。

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@SpringBootTest
@ActiveProfiles
public @interface MyApplicationTest {
@AliasFor(annotation = ActiveProfiles.class, attribute = "profiles") String[] activeProfiles() default {"test"};
}

您可以将 application.properties 文件放在您的 test/resources 文件夹中

spring.profiles.active=test

这是运行测试时的默认测试配置文件。

另一种方法是定义一个基础(抽象)测试类,您的实际测试类将扩展这个测试类:

@RunWith(SpringRunner.class)
@SpringBootTest()
@ActiveProfiles("staging")
public abstract class BaseIntegrationTest {
}

混凝土试验:

public class SampleSearchServiceTest extends BaseIntegrationTest{


@Inject
private SampleSearchService service;


@Test
public void shouldInjectService(){
assertThat(this.service).isNotNull();
}
}

这允许您提取不仅仅是 @ActiveProfiles注释的内容。您还可以为不同类型的集成测试设想更专业的基类,例如数据访问层与服务层,或者功能特性(常见的 @Before@After方法等)。

在我的例子中,根据环境的不同,我有不同的 application.properties,比如:

application.properties (base file)
application-dev.properties
application-qa.properties
application-prod.properties

Properties 包含一个属性 spring.profiles.active 来选择合适的文件。

对于我的集成测试,我在 test/resources中创建了一个新的 application-test.properties文件,使用 @TestPropertySource({ "/application-test.properties" })注释,这个文件负责根据我对这些测试的需要选择 application.properties

另一种程序化的方法是:

  import static org.springframework.core.env.AbstractEnvironment.DEFAULT_PROFILES_PROPERTY_NAME;


@BeforeClass
public static void setupTest() {
System.setProperty(DEFAULT_PROFILES_PROPERTY_NAME, "test");
}

效果很好。

在 application.properties 文件中添加 spring.profiles.active=tests,您可以在您的 Spring 启动应用程序中添加多个属性文件,如 application-stage.propertiesapplication-prod.properties等。并且可以通过添加 spring.profiles.active=stagespring.profiles.active=prod在 application.properties 文件中指定引用的 while 文件

您还可以在运行 Spring 启动应用程序时通过以下命令传递配置文件:

java -jar-Dspring.profiles.active=localbuild/libs/turtle-rnr-0.0.1-SNAPSHOT.jar

根据配置文件的名称,将拾取属性文件,在上述情况下,传递配置文件 local时考虑 application-local.properties文件

要激活“测试”配置文件,请在 build.gradle 中写入:

    test.doFirst {
systemProperty 'spring.profiles.active', 'test'
activeProfiles = 'test'
}

一个相对的方法来做到这一点(事实上,在@Compito 最初的回答中只用了一个小小的 twitter) :

  1. test/resources/application-default.properties中设置 spring.profiles.active=test
  2. 为测试添加 test/resources/application-test.properties,并只重写所需的属性。

如果使用 maven,可以将其添加到 pom.xml 中:

<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<configuration>
<argLine>-Dspring.profiles.active=test ${argLine}</argLine>
</configuration>
</plugin>
...

然后,maven 应该使用这个参数运行集成测试(* IT.java) ,IntelliJ 也将从这个概要文件激活开始——这样您就可以在其中指定所有属性

application-test.yml

而且您不应该需要“-default”属性。

更新

添加了 ${argLine}以便与其他插件(例如 jacoco)一起工作

如果您只是想在通过 maven 进行构建时设置/使用缺省配置文件,那么传递参数 -Dspring.profiles.active=test 就像

Mvn clean install-Dspring.profiles.active = dev

您可以将测试特定的属性放入 src/test/resources/config/application.properties中。

此文件中定义的属性将在测试期间覆盖在 src/main/resources/application.properties中定义的属性。

更多的信息,为什么这个工程有一个看看 Spring Boots 的文件

有两种方法。

config/加载

(2022年更新,针对 Spring Boot 2.6进行了测试)

除了下面的方法之外,还可以向 src/test/resources/config/application.yml添加配置

src/
├── main/
│   ├── java/
│   │   └── ...
│   └── resources/
│       └── application.yml <- default properties, always loaded
└── test/
├── java/
│   └── ...
└── resources/
└── config/
└── application.yml <- test properties, will override the defaults

Https://docs.spring.io/spring-boot/docs/current/reference/html/features.html#features.external-config.files

当应用程序启动时,Spring Boot 将自动从以下位置查找和加载 application.propertiesapplication.yaml文件:

  1. 从类路径
    1. 类路径根
    2. 类路径 /config
  2. 工作目录
    1. 工作目录
    2. 工作目录中的 /config子目录
    3. /config子目录的直接子目录

该列表按优先级排序(来自较低项的值覆盖较早项的值)。来自加载文件的文档作为 PropertySources添加到 SpringEnvironment

使用 spring.config.import手动导入

(2021年的原始答案,针对 Spring Boot 2.4进行了测试)

一种解决方案是拥有3个属性文件并导入

  • src/main/resources/application.yml-包含应用程序的默认道具
  • src/test/resources/application.yml-将配置文件设置为“ test”,并从“ main”导入属性
  • src/test/resources/application-test.yml-包含特定于测试的配置文件,它将覆盖“ main”

以下是 src/test/resources/application.yml的内容:

# for testing, set default profile to 'test'
spring.profiles.active: "test"
# and import the 'main' properties
spring.config.import: file:src/main/resources/application.yml

例如,如果 src/main/resources/application.yml具有

ip-address: "10.7.0.1"
username: admin

src/test/resources/application-test.yml已经

ip-address: "999.999.999.999"
run-integration-test: true

然后(假设没有其他配置文件) ..。

在做测试的时候,

profiles=test
--
ip-address=999.999.999.999
username=admin
run-integration-test=true

以及正常运行应用程序时

profiles=none
--
ip-address=10.7.0.1
username=admin
run-integration-test <undefined>

注意: 如果 src/main/resources/application.yml包含 spring.profiles.active: "dev",那么这将不会被 src/test/resources/application-test.yml覆盖

我通常使用公共代码和注释为所有集成测试创建一个基类。不要忘记使它 abstract为了不安装。例如:

@SpringBootTest
@Transactional
@AutoConfigureMockMvc
@ActiveProfiles("test")
public abstract class AbstractControllerTest {


@Autowired
protected MockMvc mockMvc;


protected ResultActions perform(MockHttpServletRequestBuilder builder) throws Exception {
return mockMvc.perform(builder);
}
}


// All annotations are inherited
class AccountControllerTest extends AbstractControllerTest {
....

我找到的最好的解决方案是这里的最后一个建议: < a href = “ https://inspeerity.com/blog/set-default-spring-profile-for-test-with-overage-option/”rel = “ nofollow norefrer”> https://inspeerity.com/blog/setting-default-spring-profile-for-tests-with-override-option/ 作者还非常清楚地描述了这个问题,并讨论了我能想到的其他方法的缺点。

在测试资源中创建一个文件 application-default.properties,其中包含一行:

spring.profiles.active=test

这利用了这样一个事实: 如果没有显式设置其他概要文件,Spring 会自动启用“缺省”概要文件。现在,您的 application-test.properties文件将在默认情况下用于所有测试。