对于我的一个Spring bean(比如Application类),我使用@Value注释从属性文件(prop.properties)中获取属性的值(my.property.flag = true / false) 。这完全没问题。
我需要编写一个集成测试(比如说ApplicationIt类),我需要测试该属性的值,即true和false。
在我的属性文件中,属性的值设置为true。是否可以从我的Integration测试中将值动态设置为false?
例如,
prop.properties:
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?
}
答案 0 :(得分:8)
您可以在测试类上指定测试属性,如下所示:
@RunWith(SpringRunner.class)
@TestPropertySource(properties = {"spring.main.banner-mode=off", "my.property.flag=false"})
public class MyTest {
由于Spring具有完整的属性覆盖层次结构,因此非常有效,缺点是您需要针对不同值的单独测试类。如果您正在使用Spring Boot,那么另一个注释可提供相同的功能,但也有更多选项可用于配置您的测试环境。例如:
@SpringBootTest(properties = {"spring.main.banner-mode=off", "my.property.flag=false"})
同样,您将需要单独的测试类来处理硬编码的测试属性。
答案 1 :(得分:5)
我被这个问题搞砸了一段时间,发现这种方法可以覆盖属性。如果您需要对应用程序上下文进行某些编程初始化(例如注册属性源,而不仅仅是这种情况),那么它非常有用。以下方法使用ContextConfiguration
' s initializers
。
Spring Boot 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));
}
}
}
Spring Boot 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) {
TestPropertyValues.of(
"spring.redis.host:" + redis.getContainerIpAddress(),
"spring.redis.port:" + redis.getMappedPort(REDIS_PORT))
.applyTo(ctx);
}
}
}
答案 2 :(得分:3)
我想提一下旧的反思方式。在组件中连接后,可以使用spring提供的实用程序类:
ReflectionTestUtils.setField(component, "isTrue", true)
您可以在随后的测试中将其更改为您想要的任何值
答案 3 :(得分:1)
最好使用构造函数注入而不是场注入:
@Component
class Application {
Application(@Value("${my.property.flag}") boolean flag) {
...
}
}
这使得使用模拟或测试值就像传递参数一样简单。