【问题标题】:Replace @Value property within @Configuration during Spring Boot test在 Spring Boot 测试期间替换 @Configuration 中的 @Value 属性
【发布时间】:2018-12-18 18:21:05
【问题描述】:

场景

我有一个带有 @Configuration 注释 Spring 配置类的 Spring Boot 应用程序,其中包含一些 @Value 注释字段。为了测试,我想用自定义测试值替换这些字段值。

不幸的是,这些测试值不能使用简单的属性文件、(字符串)常量或类似文件来覆盖,而是我必须使用一些自定义的写入属性来解析 Java 类(例如 TargetProperties.getProperty("some.username"))。

我遇到的问题是,当我在测试配置中将自定义 PropertySource 添加到 ConfigurableEnvironment 时,已经太晚了,因为这个 PropertySource 将被添加 例如RestTemplate 已创建。

问题

我怎样才能覆盖@Value 带注释的字段 @Configuration 类中以编程方式 通过自定义Java 代码获得的属性之前被初始化了吗?

代码

生产配置类

@Configuration
public class SomeConfiguration {

    @Value("${some.username}")
    private String someUsername;

    @Value("${some.password}")
    private String somePassword;

    @Bean
    public RestTemplate someRestTemplate() {
        RestTemplate restTemplate = new RestTemplate();

        restTemplate.getInterceptors().add(
            new BasicAuthorizationInterceptor(someUsername, somePassword));

        return restTemplate;
    }

}

测试配置类

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE)
public class SomeTest {

    @SpringBootConfiguration
    @Import({MySpringBootApp.class, SomeConfiguration.class})
    static class TestConfiguration {

        @Autowired
        private ConfigurableEnvironment configurableEnvironment;

        // This doesn't work:

        @Bean
        @Lazy(false)
        // I also tried a @PostConstruct method
        public TargetPropertiesPropertySource targetPropertiesPropertySource() {
            TargetPropertiesPropertySource customPropertySource =
                new TargetPropertiesPropertySource();
            configurableEnvironment.getPropertySources().addFirst(customPropertySource);
            return customPropertySource;
        }
    }
}

【问题讨论】:

    标签: testing spring-boot


    【解决方案1】:

    您可以使用properties 参数直接在@SpringBootTest 注释中覆盖属性:

    @SpringBootTest(properties = {"some.username=user", "some.password=pwd"},
                    webEnvironment = SpringBootTest.WebEnvironment.NONE)
    

    【讨论】:

    • 这对于常见/大多数情况是正确的,但我的情况不同,我必须以编程方式检索这些值
    【解决方案2】:

    您可以使用@TestPropertySource

    @TestPropertySource(
        properties = {
            "some.username=validate",
            "some.password=false"
        }
    )
    @RunWith(SpringRunner.class)
    @SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
    public class ApplicationTest {
        //...
    }
    

    【讨论】:

    • 这对于常见/大多数情况是正确的,但我的情况不同,我必须以编程方式检索这些值
    【解决方案3】:

    您可以在生产案例中使用构造函数注入,这允许它手动设置配置:

    @Configuration
    public class SomeConfiguration {
    
        private final String someUsername;
        private final String somePassword;
    
        @Autowired
        public SomeConfiguration(@Value("${some.username}") String someUsername,
           @Value("${some.password}") String somePassword) {
           this.someUsername = someUsername;
           this.somePassword = somePassword;
        }
    ...
    )
    }
    
    @RunWith(SpringRunner.class)
    @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE)
    public class SomeTest {
    
        private SomeConfiguration config;
    
        @Before
        public init() {
          config = new SomeConfiguration("foo", "bar");
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-04-15
      • 2016-12-27
      • 2020-05-03
      • 2017-01-20
      • 2022-01-14
      • 2013-06-25
      • 2019-10-19
      • 1970-01-01
      相关资源
      最近更新 更多