在集成测试中覆盖@Value

San*_*ndy 6 java spring integration-testing spring-test

对于我的一个Spring bean(比如Application类),我使用@Value注释从属性文件(prop.properties)中获取属性的值(my.property.flag = true/false).这完全没问题.

我需要编写一个集成测试(比如说ApplicationIt类),我需要测试属性的值,即true和false.

在我的属性文件中,属性的值设置为true.是否可以从我的Integration测试中将值动态设置为false?

例如,

prop.properties:

    my.property.flag=true
Run Code Online (Sandbox Code Playgroud)

应用程序类文件:

    @Component
    class Application {
        //This value is fetched from properties file
        //the value is set to true.
        @Value(${my.property.flag})
        private String isTrue;
        ......
        ..........
    }
Run Code Online (Sandbox Code Playgroud)

整合测试:

    class ApplicationIT {
        //how can I set the value of isTrue here to false?
    }
Run Code Online (Sandbox Code Playgroud)

ngr*_*een 11

您可以在测试类上指定测试属性,如下所示:

@RunWith(SpringRunner.class)
@TestPropertySource(properties = {"spring.main.banner-mode=off", "my.property.flag=false"})
public class MyTest {
Run Code Online (Sandbox Code Playgroud)

由于Spring具有完整的属性覆盖层次结构,因此非常有效,缺点是您需要针对不同值的单独测试类.如果您使用的是Spring Boot,则会有另一个注释提供相同的功能,但也有更多选项可用于配置您的测试环境.例:

@SpringBootTest(properties = {"spring.main.banner-mode=off", "my.property.flag=false"})
Run Code Online (Sandbox Code Playgroud)

同样,您将需要单独的测试类来处理硬编码的测试属性.


dev*_*Fun 8

我想提一下很好的旧反思方式。在连接到组件后,您可以使用 spring 提供的实用程序类:

ReflectionTestUtils.setField(component, "isTrue", true)
Run Code Online (Sandbox Code Playgroud)

您可以在随后的测试中将其更改为您想要的任何值


mag*_*ter 7

我有一段时间对此进行了修改,并发现了这种覆盖属性的简洁方法.如果您需要对应用程序上下文进行某些编程初始化(例如注册属性源,而不仅仅是这种情况),那么它非常有用.以下方法使用ContextConfigurationinitializers.

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));
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)