ChatGPT解决这个技术问题 Extra ChatGPT

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

Spring-boot 利用 Spring profiles 允许例如为不同的环境进行单独的配置。我使用此功能的一种方法是配置测试数据库以供集成测试使用。但是我想知道是否有必要创建我自己的配置文件“测试”并在每个测试文件中明确激活此配置文件?现在我通过以下方式做到这一点:

在 src/main/resources 中创建 application-test.properties 在此处写入特定于测试的配置(现在只是数据库名称) 在每个测试文件中包括:@ActiveProfiles("test")

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

编辑 1:这个问题与 Spring-Boot 1.4.1 相关


C
Community

据我所知,没有什么可以直接解决您的要求 - 但我可以提出一个可以帮助的建议:

您可以使用自己的测试注释,它是由 @SpringBootTest@ActiveProfiles("test") 组成的 meta annotation。因此,您仍然需要专用配置文件,但要避免将配置文件定义分散到所有测试中。

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

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

如何使用它来声明注释要使用的多个活动配置文件?
A
AmirHd

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

@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 方法等)。


我们可以在这里有一个接口而不是一个类吗?
C
Compito

您可以将 application.properties 文件放在您的 test/resources 文件夹中。你在那里设置

spring.profiles.active=test

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


如果我想避免设置@ActiveProfiles("test"),我会在我的测试用例中使用这个条目。它不适合你吗?
如果我创建 src/test/resources/application.properties 文件,则在运行测试时会忽略 src/main/resources/application.properties 内容。
@ciastek 您可以为测试添加 application-test.properties 并仅覆盖您需要的属性。
@Advicer 除非默认属性指定 spring.profiles.active=test ,否则不会被选中,就像答案所说的那样。
@OrangeDog 完全正确-也许您可以使用默认情况下处于活动状态的配置文件“默认”。所以你可以在 test/resources/application-default.properties 添加这样一行(当然除非你已经有一个 src/main/application-default.properties 文件:-)
a
aSemy

有两种方法。

从配置加载/

(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.properties 和 application.yaml 文件: 从类路径 类路径根 类路径 /config 包 从当前目录 当前目录 当前目录下的 /config 子目录/config 子目录的直接子目录 该列表按优先级排序(较低项目的值覆盖较早的项目)。加载文件中的文档作为 PropertySources 添加到 Spring 环境中。

使用 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 覆盖


奇怪的是,没有 src/test/resources/application.yml 文件,environment.getActiveProfiles() 仍会返回正确的测试配置文件,但如果我通过 @Value("${spring.profiles.active:}") 注释获得活动配置文件,它将为空。
J
JohnW

一种说明性的方法(事实上,与@Compito 的原始答案相比,这是一个小小的 tweek):

在 test/resources/application-default.properties 中设置 spring.profiles.active=test。为测试添加 test/resources/application-test.properties 并仅覆盖您需要的属性。


这是否意味着类路径中的默认 application.properties 也被解析,然后是 test/resources/application-default.properties,然后,因为检测到配置文件“test”,所以 test/resources/application-test.properties 被解析?否则,它不会解决 @Compito's answer 下评论的 @ciastek 的问题。
我在使用 Spring Boot 2.4.5 时收到此错误:“从位置‘类路径资源 [application-default.yml]’导入的属性‘spring.profiles.active’在配置文件特定资源中无效 [来源:类路径资源 [应用程序-default.yml]"
M
Matze

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

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

如需详细了解此功能为何有效,请查看 Spring Boots docs


这里的许多好主意对许多情况都很有用。恕我直言 @Matze 答案是这个问题的最简洁和直接的答案,不需要配置文件,不需要修改测试代码......而且日志记录也更干净(在我的情况下,Spring 记录使用方言时令人困惑:org.hibernate.dialect.PostgreSQL93Dialect谢天谢地,当我的测试是使用测试 H2 数据库时)。
哇,我没想到会在列表中找到这么深的正确答案。
B
Bojan Vukasovic

如果你使用 maven,你可以在 pom.xml 中添加这个:

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

然后,maven 应该使用这个参数运行你的集成测试(*IT.java),并且 IntelliJ 将从激活这个配置文件开始 - 这样你就可以指定里面的所有属性

application-test.yml

你不应该需要“-default”属性。


为我工作,但必须向surefire插件添加配置以及故障保护。
D
Demel

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

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

E
Eduardo

就我而言,我有不同的 application.properties 取决于环境,例如:

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

并且 application.properties 包含一个属性 spring.profiles.active 来选择正确的文件。

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


您应该使用 @ActiveProfiles,而不是 @TestPropertySource
我认为使用@TestPropertiesSource 并不介意。这也是在配置文件测试配置之间加载配置的方式。
V
Valtoni Boaventura

另一种以编程方式执行此操作的方法:

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

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

它工作得很好。


R
Rajan Mishra

如果您只是想在通过 maven 构建时设置/使用默认配置文件,则传递参数 -Dspring.profiles.active=test 就像

mvn clean install -Dspring.profiles.active=dev


G
Grigory Kislin

我通常使用通用代码和注释为所有集成测试完成一个基类。不要忘记将其设为 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 {
....

M
Michael Knopf

我找到的最佳解决方案是这里的最后一个建议:https://inspeerity.com/blog/setting-default-spring-profile-for-tests-with-override-option/ 作者还非常清楚地描述了这个问题,并讨论了我能想到的所有其他方法的缺点。

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

spring.profiles.active=test

这利用了这样一个事实,即如果没有明确设置其他配置文件,Spring 会自动启用“默认”配置文件。现在,您的 application-test.properties 文件将默认用于所有测试。


实际上,从 Spring Boot 2.4 开始似乎不再支持此功能... stackoverflow.com/questions/67935961/…
B
Bishal Jaiswal

在 application.properties 文件中添加 spring.profiles.active=tests,您可以在 spring boot 应用程序中添加多个属性文件,如 application-stage.propertiesapplication-prod.properties 等。您可以在 application.properties 文件中指定要通过添加 { 4} 或 spring.profiles.active=prod

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

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

根据配置文件名称选择属性文件,在上述情况下,通过配置文件 local 考虑 application-local.properties 文件