Java 在集成测试中重写@Value
对于我的一个Springbean(比如应用程序类),我使用@value注释从属性文件(prop.properties)获取属性值(my.property.flag=true/false)。那很好用 我需要编写一个集成测试(比如ApplicationIt类),其中我需要使用属性的两个值进行测试,即true和false 在我的属性文件中,属性的值设置为true。是否可以从集成测试中将该值动态设置为false 比如说, 道具属性:Java 在集成测试中重写@Value,java,spring,integration-testing,spring-test,Java,Spring,Integration Testing,Spring Test,对于我的一个Springbean(比如应用程序类),我使用@value注释从属性文件(prop.properties)获取属性值(my.property.flag=true/false)。那很好用 我需要编写一个集成测试(比如ApplicationIt类),其中我需要使用属性的两个值进行测试,即true和false 在我的属性文件中,属性的值设置为true。是否可以从集成测试中将该值动态设置为false 比如说, 道具属性: my.property.flag=true @Com
my.property.flag=true
@Component
class Application {
//This value is fetched from properties file
//the value is set to true.
@Value(${my.property.flag})
private String isTrue;
......
..........
}
class ApplicationIT {
//how can I set the value of isTrue here to false?
}
应用程序类文件:
my.property.flag=true
@Component
class Application {
//This value is fetched from properties file
//the value is set to true.
@Value(${my.property.flag})
private String isTrue;
......
..........
}
class ApplicationIT {
//how can I set the value of isTrue here to false?
}
集成测试:
my.property.flag=true
@Component
class Application {
//This value is fetched from properties file
//the value is set to true.
@Value(${my.property.flag})
private String isTrue;
......
..........
}
class ApplicationIT {
//how can I set the value of isTrue here to false?
}
可以按如下方式指定测试类上的测试属性:
@RunWith(SpringRunner.class)
@TestPropertySource(properties = {"spring.main.banner-mode=off", "my.property.flag=false"})
public class MyTest {
因为Spring有一个完整的属性重写层次结构,所以它工作得很好,缺点是您需要为不同的值使用不同的测试类。如果您使用的是SpringBoot,那么还有另一个注释提供了相同的功能,但也有更多用于配置测试环境的选项。例如:
@SpringBootTest(properties = {"spring.main.banner-mode=off", "my.property.flag=false"})
同样,您需要单独的测试类来处理硬编码的测试属性。最好使用构造函数注入而不是字段注入:
@Component
class Application {
Application(@Value("${my.property.flag}") boolean flag) {
...
}
}
这使得使用mock或test值就像传递参数一样简单。我想提到一种很好的旧反射方式。在连接组件后,可以使用spring提供的实用程序类:
ReflectionTestUtils.setField(component, "isTrue", true)
您可以在后续测试中将其更改为您想要的任何值我对此进行了一段时间的调试,并找到了一种覆盖属性的简洁方法。如果您需要对应用程序上下文进行一些编程初始化,例如像在这种情况下一样注册属性源,那么它非常有用,但不仅仅是这样。以下方法使用
ContextConfiguration
的初始值设定项
弹簧靴1.5.x的示例:
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT, properties = {"management.port=0"})
@ContextConfiguration(initializers = AbstractIntegrationTest.Initializer.class)
@DirtiesContext
public abstract class AbstractIntegrationTest {
private static int REDIS_PORT = 6379;
@ClassRule
public static GenericContainer redis = new GenericContainer("redis:3.0.6").withExposedPorts(REDIS_PORT);
public static class Initializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
@Override
public void initialize(ConfigurableApplicationContext ctx) {
TestPropertySourceUtils.addInlinedPropertiesToEnvironment(ctx,
"spring.redis.host=" + redis.getContainerIpAddress(),
"spring.redis.port=" + redis.getMappedPort(REDIS_PORT));
}
}
}
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT, properties = {"management.port=0"})
@ContextConfiguration(initializers = AbstractIntegrationTest.Initializer.class)
@DirtiesContext
public abstract class AbstractIntegrationTest {
private static int REDIS_PORT = 6379;
@ClassRule
public static GenericContainer redis = new GenericContainer("redis:3.0.6").withExposedPorts(REDIS_PORT);
public static class Initializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
@Override
public void initialize(ConfigurableApplicationContext ctx) {
TestPropertyValues.of(
"spring.redis.host:" + redis.getContainerIpAddress(),
"spring.redis.port:" + redis.getMappedPort(REDIS_PORT))
.applyTo(ctx);
}
}
}
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment=webEnvironment.RANDOM_端口,属性={“management.PORT=0”})
@ContextConfiguration(初始值设定项=AbstractIntegrationTest.Initializer.class)
@肮脏的环境
公共抽象类AbstractIntegrationTest{
私有静态int REDIS_端口=6379;
@阶级规则
公共静态GenericContainer redis=新的GenericContainer(“redis:3.0.6”)。具有公开的端口(redis\u端口);
公共静态类初始值设定项实现ApplicationContextInitializer{
@凌驾
公共无效初始化(ConfigurableApplicationContext ctx){
TestPropertySourceUtils.将线性属性添加到环境中(ctx,
“spring.redis.host=“+redis.getContainerIpAddress(),
“spring.redis.port=“+redis.getMappedPort(redis_-port));
}
}
}
弹簧靴2.x的示例:
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT, properties = {"management.port=0"})
@ContextConfiguration(initializers = AbstractIntegrationTest.Initializer.class)
@DirtiesContext
public abstract class AbstractIntegrationTest {
private static int REDIS_PORT = 6379;
@ClassRule
public static GenericContainer redis = new GenericContainer("redis:3.0.6").withExposedPorts(REDIS_PORT);
public static class Initializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
@Override
public void initialize(ConfigurableApplicationContext ctx) {
TestPropertySourceUtils.addInlinedPropertiesToEnvironment(ctx,
"spring.redis.host=" + redis.getContainerIpAddress(),
"spring.redis.port=" + redis.getMappedPort(REDIS_PORT));
}
}
}
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT, properties = {"management.port=0"})
@ContextConfiguration(initializers = AbstractIntegrationTest.Initializer.class)
@DirtiesContext
public abstract class AbstractIntegrationTest {
private static int REDIS_PORT = 6379;
@ClassRule
public static GenericContainer redis = new GenericContainer("redis:3.0.6").withExposedPorts(REDIS_PORT);
public static class Initializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
@Override
public void initialize(ConfigurableApplicationContext ctx) {
TestPropertyValues.of(
"spring.redis.host:" + redis.getContainerIpAddress(),
"spring.redis.port:" + redis.getMappedPort(REDIS_PORT))
.applyTo(ctx);
}
}
}
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment=webEnvironment.RANDOM_端口,属性={“management.PORT=0”})
@ContextConfiguration(初始值设定项=AbstractIntegrationTest.Initializer.class)
@肮脏的环境
公共抽象类AbstractIntegrationTest{
私有静态int REDIS_端口=6379;
@阶级规则
公共静态GenericContainer redis=新的GenericContainer(“redis:3.0.6”)。具有公开的端口(redis\u端口);
公共静态类初始值设定项实现ApplicationContextInitializer{
@凌驾
公共无效初始化(ConfigurableApplicationContext ctx){
TestPropertyValue.of(
“spring.redis.host:”+redis.getContainerIpAddress(),
spring.redis.port:“+redis.getMappedPort(redis_-port))
.applyTo(ctx);
}
}
}
您可以使用测试覆盖创建单独的属性文件。此属性文件中有许多属性,我的要求仅适用于单个属性。我认为仅仅为这一个属性创建一个新的属性文件是不够明智的。您可能想检查这一点是的,但是如何在集成测试中以动态方式重写-例如,以便在测试执行期间确定和设置my.propery.flag