如何使用 spring-boot-test 中的 ApplicationContextRunner 测试 @ConfigurationProperties?

Gui*_*che 5 spring-boot spring-boot-test

我需要测试使用@ConfigurationProperties bean 的自动配置类。我正在使用https://docs.spring.io/spring-boot/docs/current/reference/html/spring-boot-features.html#boot-features-test-autoconfig 中记录的 ApplicationContextRunner进行测试更快并避免在每个变体之间启动 servlet 容器。但是,使用 @AutoconfigurationProperties 注释的 bean 不会填充注入 ApplicationContextRunner 的值。

我怀疑我遇到了类似于/sf/answers/3921617031/ 的问题

@ConfigurationProperties 不受您在测试中构建的应用程序上下文管理,尽管它们会在应用程序启动时加载,因为您的应用程序主类上有 @EnableConfigurationProperties。

如何使用 ApplicationContextRunner 启用对 @ConfigurationProperties 的支持?

下面是对应的代码

    @Test
    void ServiceDefinitionMapperPropertiesAreProperlyLoaded() {
        ApplicationContextRunner contextRunner = new ApplicationContextRunner()
            .withConfiguration(AutoConfigurations.of(
                SingleServiceDefinitionAnswerAutoConfig.class,
                DynamicCatalogServiceAutoConfiguration.class
            ))
//          .withPropertyValues(DynamicCatalogProperties.OPT_IN_PROPERTY + "=true") //Not sure why this seems ignored
            .withSystemProperties(DynamicCatalogConstants.OPT_IN_PROPERTY + "=true",
                ServiceDefinitionMapperProperties.PROPERTY_PREFIX
                +ServiceDefinitionMapperProperties.SUFFIX_PROPERTY_KEY+ "=suffix")
        ;
        contextRunner.run(context -> {
            assertThat(context).hasSingleBean(ServiceDefinitionMapperProperties.class);
            ServiceDefinitionMapperProperties serviceDefinitionMapperProperties
                = context.getBean(ServiceDefinitionMapperProperties.class);
            assertThat(serviceDefinitionMapperProperties.getSuffix()).isEqualTo("suffix");
        });
    }
Run Code Online (Sandbox Code Playgroud)

失败了:

 org.opentest4j.AssertionFailedError: 
Expecting:
 <"">
to be equal to:
 <"suffix">
but was not.
Expected :suffix
Actual   :
<Click to see difference>
    at org.springframework.cloud.appbroker.autoconfigure.DynamicCatalogServiceAutoConfigurationTest
Run Code Online (Sandbox Code Playgroud)
 org.opentest4j.AssertionFailedError: 
Expecting:
 <"">
to be equal to:
 <"suffix">
but was not.
Expected :suffix
Actual   :
<Click to see difference>
    at org.springframework.cloud.appbroker.autoconfigure.DynamicCatalogServiceAutoConfigurationTest
Run Code Online (Sandbox Code Playgroud)

完整来源可在https://github.com/orange-cloudfoundry/osb-cmdb-spike/blob/0da641e5f2f811f48b0676a25c8cbe97895168d1/spring-cloud-app-broker-autoconfigure/src/test/java/org/springframework/cloud/appbroker自动配置/动态目录服务AutoConfigurationTest.java#L89-L107

ps:我正要向https://github.com/spring-projects/spring-boot/issues提交一个问题,以建议增强文档以警告 ApplicationContext 中的此类限制,并寻求打开对 @ 的支持的方法配置属性。按照https://raw.githubusercontent.com/spring-projects/spring-boot/master/.github/ISSUE_TEMPLATE.md 的指导,我首先要确保我没有误解这个问题。

Ken*_*ter 7

如果您想@ConfigurationProperties在测试中填充带有类注释的 bean,并且通常依赖于带有注释的配置类来@EnableConfigurationProperties填充该 bean,那么您可以为测试创建一个简单的配置类:

@ConfigurationProperties("app")
public class ConfigProps {
    private int meaningOfLife;

    public int getMeaningOfLife() { return meaningOfLife; }
    public void setMeaningOfLife(int meaning) { this.meaningOfLife = meaning; }
}

class ConfigPropsTest {

    private final ApplicationContextRunner runner = new ApplicationContextRunner();

    @EnableConfigurationProperties(ConfigProps.class)
    static class TrivialConfiguration {
    }

    @Test
    void test() {
        runner.withUserConfiguration(TrivialConfiguration.class)
            .withPropertyValues("app.meaning-of-life=42")
            .run(context -> {
                assertEquals(42, context.getBean(ConfigProps.class).getMeaningOfLife());
            });
    }

}
Run Code Online (Sandbox Code Playgroud)

传递TrivialConfigurationApplicationContextRunner足以使其ConfigProps使用可用属性创建并填充它。


And*_*son 5

据我所知,您的测试中涉及的所有类都没有启用配置属性绑定。因此,没有属性绑定到ServiceDefinitionMapperProperties。您可以使用 启用配置属性绑定@EnableConfigurationProperties。添加它的典型位置是 on,DynamicCatalogServiceAutoConfiguration因为它的serviceDefinitionMapperPropertiesbean 依赖于启用的配置属性。