我有一个Spring-Boot应用程序,其中在应用程序中设置了默认属性。属性文件在类路径(src/main/resources/application.properties)。
我想用测试中声明的属性覆盖JUnit测试中的一些默认设置。属性文件(src/test/resources/test. Properties)
我通常为我的Junit测试有一个专用的配置类,例如。
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 {
}
我最初认为在TestConfig类中使用@PropertySource("classpath:test.properties")可以达到目的,但是这些属性不会覆盖应用程序。属性设置(参见Spring-Boot参考文档- 23。外部化配置)。
然后我尝试使用-Dspring.config.location=classpath:test。属性。这是成功的——但是我不想为每次测试执行都设置这个系统属性。因此我把它放在代码中
@Configuration
@Import(CoreConfig.class)
@EnableAutoConfiguration
public class TestConfig {
static {
System.setProperty("spring.config.location", "classpath:test.properties");
}
}
不幸的是,这次也没有成功。
必须有一个简单的解决方案如何覆盖应用程序。使用test在JUnit测试中设置属性。我一定是忽略了这些特性
Spring Boot自动加载src/test/resources/application。属性,如果使用以下注释
@RunWith(SpringRunner.class)
@SpringBootTest
重命名test。应用程序的属性。属性来利用自动配置。
如果您只需要加载属性文件(到环境中),您也可以使用下面的方法,如下所述
@RunWith(SpringRunner.class)
@ContextConfiguration(initializers = ConfigFileApplicationContextInitializer.class)
[更新:覆盖测试的某些属性]
添加src /主/资源/ application-test.properties。
用@ActiveProfiles(“test”)注释测试类。
这将加载应用程序。属性,然后应用程序测试。根据这里定义的规则,将属性放入测试用例的应用程序上下文中。
演示- https://github.com/mohnish82/so-spring-boot-testprops
TLDR:
我所做的就是创建标准的src/main/resources/application。属性和src/test/resources/application-default。属性,我覆盖一些设置为我所有的测试。
power-developers:
为了更容易地改变/使用不同的spring配置文件,我现在有一个应用程序默认。它声明了我想要使用的概要文件。
这个文件是不提交的,所以每个开发人员可以选择他/她正在工作的配置文件和需求(例如功能)的激活方式。
spring:
profiles:
include:
- local
- devlocal
- wip
# - kafka@docker
---
spring.profiles: wip
# ... overriding properties
整个故事
我遇到了同样的问题,到目前为止也没有使用配置文件。现在必须这样做,并记得声明概要文件似乎很麻烦——这很容易忘记。
诀窍在于,利用特定于概要文件的应用程序-<profile>。属性将覆盖常规配置文件中的设置。见https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html # boot-features-external-config-profile-specific-properties。
如果你和我一样有同样的应用。src/main/resources和src/test/resources中的属性,你想知道为什么应用程序。属性不会覆盖应用程序。属性在你的主要资源,阅读…
简单的解释:
If you have application.properties under src/main/resources and the same application.properties under src/test/resources, which application.properties gets picked up, depends on how you are running your tests. The folder structure src/main/resources and src/test/resources, is a Maven architectural convention, so if you run your test like mvnw test or even gradlew test, the application.properties in src/test/resources will get picked up, as test classpath will precede main classpath. But, if you run your test like Run as JUnit Test in Eclipse/STS, the application.properties in src/main/resources will get picked up, as main classpath precedes test classpath.
您可以通过打开菜单栏查看运行>运行配置> JUnit > *your_run_configuration* >单击“显示命令行”。
你会看到这样的东西:
XXXbin\javaw.exe -ea -Dfile。编码= UTF-8 -classpath
XXX \ workspace-spring-tool-suite-4-4 5。1 .发布project_name \ bin \玩;
XXX \ workspace-spring-tool-suite-4-4 5。1 .发布project_name \ bin \测试;
你看到类路径xxx\main先出现,然后是xxx\test吗?对,这都是关于类路径的:-)
附注:
注意在启动配置中覆盖的属性(例如在Spring Tool Suite IDE中)优先于application.properties。
改变顺序:
现在,在Spring中一切都是可配置的。你可以改变构建类路径,让xxx\test先出现,然后是xxx\main。
简单地转到项目>属性> Java构建路径>顺序和导出,通过将任何测试文件夹放在前面来更改构建类路径顺序,例如:
就是这样!
更好的解决方案
一个更好的解决方案是在测试时激活src/test/resources/application-{profile}。属性(其中profile可以测试),例如在src/main/resources/application.properties中:
spring.profiles.active =测试
这更整洁,并让您完全控制在做什么时激活哪个配置文件。
您可以创建一个弹簧。src/test/resources/META-INF中的factories文件和src/test/java中的EnvironmentPostProcessor Implementation类。
春天。工厂像
# Environment Post Processors
org.springframework.boot.env.EnvironmentPostProcessor=\
com.example.test.YourTestPropertiesConfig
YourTestPropertiesConfig.java像
package com.example.test;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.env.EnvironmentPostProcessor;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.MapPropertySource;
import java.util.HashMap;
import java.util.Map;
public class YourTestPropertiesConfig implements EnvironmentPostProcessor {
private static final Map<String, Object> testProperties = new HashMap<>();
private static final Set<String> testPropertiesFile = new HashSet<>();
static {
//Add the properties you need to take effect globally in the test directly here.
testProperties.put("spring.jackson.time-zone", "GMT");
testPropertiesFile.add("classpath:test.properties");
}
@Override
public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
environment.getPropertySources().addFirst(new MapPropertySource("TestProperties", testProperties));
for (String location : testPropertiesFile) {
try {
environment.getPropertySources().addFirst(new ResourcePropertySource(location));
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void addProperty(String key, Object value) {
testProperties.put(key, value);
}
public static void addProperty(String location) {
testPropertiesFile.add(location);
}
}
这对我来说很管用:
我的测试:
@SpringBootTest
@TestPropertySource(properties = "spring.config.additional-location=classpath:application-test.yml")
class EngineApplicationTests {
@Test
void contextLoads() {
}
}
我的版本:
plugins {
id 'org.springframework.boot' version '2.7.1'
id 'io.spring.dependency-management' version '1.0.12.RELEASE'
id 'java'
}
group = 'com.kubemachine'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '11'
repositories {
mavenCentral()
}
ext {
set('springCloudVersion', "2021.0.3")
}
我的gradle文件中唯一的测试依赖项:
testImplementation 'org.springframework.boot:spring-boot-starter-test'
我的身材里也有这个。gradle文件:
test {
useJUnitPlatform()
}
和两个属性文件:
src / main /资源/ application.yml
src /测试/资源/ application-test.yml
在这个设置中,应用程序测试。yml绝对只覆盖application.yml中的值。我不需要重复应用程序中的属性值。在application-test.yml。应用程序测试。Yml确实扩展了application.yml。