ApplicationContextRunner如何简化自动配置测试
1. 概览
众所周知,自动配置是Spring Boot的关键功能之一, 但测试自动配置可能会很棘手。
在以下部分中,我们将展示ApplicationContextRunner如何简化自动配置测试。
2. 测试自动化配置方案
ApplicationContextRunner是一个实用程序类,它运行ApplicationContext并提供AssertJ样式断言。 最好用作测试类中的字段以便共享配置,然后我们在每个测试中进行自定义:
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner();
让我们通过测试一些案例来展示它的魔力。
2.1. 测试Class Condition
在本节中,我们将测试一些使用@ConditionalOnClass和@ConditionalOnMissingClass 注解的自动配置类:
@Configuration @ConditionalOnClass(ConditionalOnClassIntegrationTest.class) protected static class ConditionalOnClassConfiguration { @Bean public String created() { return "This is created when ConditionalOnClassIntegrationTest is present on the classpath"; } } @Configuration @ConditionalOnMissingClass("com.baeldung.autoconfiguration.ConditionalOnClassIntegrationTest") protected static class ConditionalOnMissingClassConfiguration { @Bean public String missed() { return "This is missed when ConditionalOnClassIntegrationTest is present on the classpath"; } }
我们想测试自动配置是否正确实例化或跳过created和missing beans给定的预期条件。
-
ApplicationContextRunner为我们提供了withUserConfiguration方法,我们可以根据需要提供自动配置,以便为每个测试自定义ApplicationContext。
-
run 方法将 ContextConsumer 作为将断言应用于上下文的参数。 测试退出时,ApplicationContext将自动关闭:
@Test public void whenDependentClassIsPresent_thenBeanCreated() { this.contextRunner.withUserConfiguration(ConditionalOnClassConfiguration.class) .run(context -> { assertThat(context).hasBean("created"); assertThat(context.getBean("created")) .isEqualTo("This is created when ConditionalOnClassIntegrationTest is present on the classpath"); }); } @Test public void whenDependentClassIsPresent_thenBeanMissing() { this.contextRunner.withUserConfiguration(ConditionalOnMissingClassConfiguration.class) .run(context -> { assertThat(context).doesNotHaveBean("missed"); }); }
通过前面的示例,我们发现测试classpath上存在某个类的场景的简单性。但是,当类不在classpath上时,我们如何测试相反的情况呢
这就是FilteredClassLoader发挥作用的地方。它用于在运行时过滤classpath上指定的类:
@Test public void whenDependentClassIsNotPresent_thenBeanMissing() { this.contextRunner.withUserConfiguration(ConditionalOnClassConfiguration.class) .withClassLoader(new FilteredClassLoader(ConditionalOnClassIntegrationTest.class)) .run((context) -> { assertThat(context).doesNotHaveBean("created"); assertThat(context).doesNotHaveBean(ConditionalOnClassIntegrationTest.class); }); } @Test public void whenDependentClassIsNotPresent_thenBeanCreated() { this.contextRunner.withUserConfiguration(ConditionalOnMissingClassConfiguration.class) .withClassLoader(new FilteredClassLoader(ConditionalOnClassIntegrationTest.class)) .run((context) -> { assertThat(context).hasBean("missed"); assertThat(context).getBean("missed") .isEqualTo("This is missed when ConditionalOnClassIntegrationTest is present on the classpath"); assertThat(context).doesNotHaveBean(ConditionalOnClassIntegrationTest.class); }); }
2.2. 测试 Bean Condition
我们刚刚测试了 @ConditionalOnClass 和 @ConditionalOnMissingClass 注解, 现在 让我们看看使用@ConditionalOnBean和@ConditionalOnMissingBean注释时的情况。
首先, 我们同样需要 一些自动配置的类:
@Configuration protected static class BasicConfiguration { @Bean public String created() { return "This is always created"; } } @Configuration @ConditionalOnBean(name = "created") protected static class ConditionalOnBeanConfiguration { @Bean public String createOnBean() { return "This is created when bean (name=created) is present"; } } @Configuration @ConditionalOnMissingBean(name = "created") protected static class ConditionalOnMissingBeanConfiguration { @Bean public String createOnMissingBean() { return "This is created when bean (name=created) is missing"; } }
然后,我们将像上一节一样调用withUserConfiguration方法,然后发送我们的自定义配置类来测试自动配置是否在不同的条件下恰当地实例化bean或跳过createOnBean或createOnMissingBean :
@Test public void whenDependentBeanIsPresent_thenConditionalBeanCreated() { this.contextRunner.withUserConfiguration(BasicConfiguration.class, ConditionalOnBeanConfiguration.class) // ommitted for brevity } @Test public void whenDependentBeanIsNotPresent_thenConditionalMissingBeanCreated() { this.contextRunner.withUserConfiguration(ConditionalOnMissingBeanConfiguration.class) // ommitted for brevity }
2.3. 测试 Property Condition
在本节中,我们测试使用 @ConditionalOnPropertyannotations的自动配置类。
首先,我们需要这个测试的属性:
com.baeldung.service=custom
然后,我们编写嵌套的自动配置类,根据前面的属性创建bean:
@Configuration @TestPropertySource("classpath:ConditionalOnPropertyTest.properties") protected static class SimpleServiceConfiguration { @Bean @ConditionalOnProperty(name = "com.baeldung.service", havingValue = "default") @ConditionalOnMissingBean public DefaultService defaultService() { return new DefaultService(); } @Bean @ConditionalOnProperty(name = "com.baeldung.service", havingValue = "custom") @ConditionalOnMissingBean public CustomService customService() { return new CustomService(); } }
现在,我们调用withPropertyValues方法来覆盖每个测试中的属性值:
@Test public void whenGivenCustomPropertyValue_thenCustomServiceCreated() { this.contextRunner.withPropertyValues("com.baeldung.service=custom") .withUserConfiguration(SimpleServiceConfiguration.class) .run(context -> { assertThat(context).hasBean("customService"); SimpleService simpleService = context.getBean(CustomService.class); assertThat(simpleService.serve()).isEqualTo("Custom Service"); assertThat(context).doesNotHaveBean("defaultService"); }); } @Test public void whenGivenDefaultPropertyValue_thenDefaultServiceCreated() { this.contextRunner.withPropertyValues("com.baeldung.service=default") .withUserConfiguration(SimpleServiceConfiguration.class) .run(context -> { assertThat(context).hasBean("defaultService"); SimpleService simpleService = context.getBean(DefaultService.class); assertThat(simpleService.serve()).isEqualTo("Default Service"); assertThat(context).doesNotHaveBean("customService"); }); }
3. 结论
总结一下, 这篇教程主要展示 如何使用ApplicationContextRunner运行带有自定义的ApplicationContext并应用断言.
我们在这里介绍了最常用的场景,而不是列出如何自定义ApplicationContext 。
在此期间,请记住ApplicationConetxtRunner适用于非Web应用程序,因此请考虑WebApplicationContextRunner用于基于servlet的Web应用程序,ReactiveWebApplicationContextRunner用于响应式Web应用程序。
本文源代码,请访问GitHub。
原文:www.baeldung.com/spring-boot…
作者:baeldung
译者:Leesen
- python程序如何在生产和测试环境自动调用对应的配置文件
- linux下如何从自动获取ip转到手动配置ip
- 如何配置Linux服务,确保崩溃或重启后自动加以运行——第一部分:应用实例
- 如何使用Office Communicator 2005的自动配置
- 通过 spring 容器内建的 profile 功能实现开发环境、测试环境、生产环境配置自动切换
- 嵌入式linux pppoe 拨号,如何自动配置安装?
- 通过 spring 容器内建的 profile 功能实现开发环境、测试环境、生产环境配置自动切换
- Robot---如何自动定时运行测试
- [63] 测试技术常见的十一种问题之十一:在配置测试中,如何判断发现的缺陷是普通问题还是特定的配置问题?
- 如何配置CentOS7 mariadb服务在崩溃或重启后自动启动
- Mybatis 如何自动生成bean dao xml 配置文件 generatorconfig.xml (main()方法自动生成更快捷)
- 如何:配置和运行生成验证测试 (BVT)
- 配置了SSL 的web服务器,如何实现启动服务的时候自动输入密码
- 如何编写训练测试的prototxt配置文件---以Resnet为例
- 如何配置eclipse/zend studio的代码自动提示功能
- 如何配置软件测试环境
- eclipse代码自动提示设置、如何配置eclipse的代码自动提示功能?
- ActiveMQ配置详解之如何配置自动重新连接
- windows 环境下 如何 配置jdk1.6环境变量及测试
- Linux/Unix 中如何配置 Oracle Database 随服务器自动启动