spring boot测试_测试Spring Boot有条件的合理方式

spring boot测试

如果您或多或少有经验的Spring Boot用户,那么很幸运,在某些时候您可能需要遇到必须有条件地注入特定bean或配置的情况 。 它的机制是很好理解的 ,但有时这样的测试条件下(以及它们的组合)可能会导致混乱。 在这篇文章中,我们将讨论一些可行的方法(可以说是理智的)。

由于Spring Boot 1.5.x仍被广泛使用(不过,它将在今年8月向EOL迈进),因此我们会将其与Spring Boot 2.1.x一起包括在JUnit 4.x和JUnit 5.x中 。 我们将要介绍的技术同样适用于常规配置类和自动配置类。

我们将使用的示例与我们的自制日志记录有关。 让我们假设我们的Spring Boot应用程序需要一些名称为“ sample”的专用记录器bean。 但是,在某些情况下,必须禁用此记录器(或实际上使其成为noop),因此在这里,属性logging.enabled就像一个kill开关。 在此示例中,我们使用Slf4j和Logback ,但这并不是很重要。 下面的LoggingConfiguration片段反映了这个想法。

 @Configuration  public class LoggingConfiguration { @Configuration @ConditionalOnProperty (name = "logging.enabled" , matchIfMissing = true ) public static class Slf4jConfiguration { @Bean Logger logger() { return LoggerFactory.getLogger( "sample" ); } }     @Bean @ConditionalOnMissingBean Logger logger() { return new NOPLoggerFactory().getLogger( "sample" ); }  } 

那么我们将如何测试呢? Spring Boot (通常是Spring Framework )一直提供出色的测试脚手架支持 。 @SpringBootTest@TestPropertySource批注允许使用自定义属性快速引导应用程序上下文。 但是,有一个问题:它们是按测试类级别而不是每种测试方法应用的。 这当然是有道理的,但基本上需要您为每个条件组合创建一个测试类。

如果您仍然使用JUnit 4.x ,则可能会发现一个有用的技巧,它可以利用框架的隐藏的宝石EnclosedRunner

 @RunWith (Enclosed. class (Enclosed. )  public class LoggingConfigurationTest { @RunWith (SpringRunner. class ) @SpringBootTest public static class LoggerEnabledTest { @Autowired private Logger logger;         @Test public void loggerShouldBeSlf4j() { assertThat(logger).isInstanceOf(ch.qos.logback.classic.Logger. class ); } }     @RunWith (SpringRunner. class ) @SpringBootTest @TestPropertySource (properties = "logging.enabled=false" ) public static class LoggerDisabledTest { @Autowired private Logger logger;         @Test public void loggerShouldBeNoop() { assertThat(logger).isSameAs(NOPLogger.NOP_LOGGER); } }  } 

您仍然可以按条件获得类,但至少它们都在同一嵌套中。 使用JUnit 5.x ,有些事情变得容易了,但并没有达到人们期望的水平。 不幸的是, Spring Boot 1.5.x本身并不支持JUnit 5.x ,因此我们必须依靠spring-test-junit5社区模块提供的扩展。 这是pom.xml中的相关更改,请注意, spring-boot-starter-test依赖关系图中明确排除了junit

 < dependency > < groupId >org.springframework.boot</ groupId > < artifactId >spring-boot-starter-test</ artifactId > < scope >test</ scope > < exclusions > < exclusion > < groupId >junit</ groupId > < artifactId >junit</ artifactId > </ exclusion > </ exclusions >  </ dependency >  < dependency > < groupId >com.github.sbrannen</ groupId > < artifactId >spring-test-junit5</ artifactId > < version >1.5.0</ version > < scope >test</ scope >  </ dependency >  < dependency > < groupId >org.junit.jupiter</ groupId > < artifactId >junit-jupiter-api</ artifactId > < version >5.5.0</ version > < scope >test</ scope >  </ dependency >  < dependency > < groupId >org.junit.jupiter</ groupId > < artifactId >junit-jupiter-engine</ artifactId > < version >5.5.0</ version > < scope >test</ scope >  </ dependency > 

除了使用@Nested批注(来自JUnit 5.x以支持将测试作为内部类)外,测试用例本身没有太大区别。

 public class LoggingConfigurationTest { @Nested @ExtendWith (SpringExtension. class ) @SpringBootTest @DisplayName ( "Logging is enabled, expecting Slf4j logger" ) public static class LoggerEnabledTest { @Autowired private Logger logger;         @Test public void loggerShouldBeSlf4j() { assertThat(logger).isInstanceOf(ch.qos.logback.classic.Logger. class ); } }     @Nested @ExtendWith (SpringExtension. class ) @SpringBootTest @TestPropertySource (properties = "logging.enabled=false" ) @DisplayName ( "Logging is disabled, expecting NOOP logger" ) public static class LoggerDisabledTest { @Autowired private Logger logger;         @Test public void loggerShouldBeNoop() { assertThat(logger).isSameAs(NOPLogger.NOP_LOGGER); } }  } 

如果您尝试使用Apache Maven和Maven Surefire插件从命令行运行测试,则可能会惊讶地发现在构建过程中没有执行任何测试。 问题是… 排除了所有嵌套类 …因此我们需要采用另一种解决方法 。

 < plugin > < groupId >org.apache.maven.plugins</ groupId > < artifactId >maven-surefire-plugin</ artifactId > < version >2.22.2</ version > < configuration > < excludes > < exclude /> </ excludes > </ configuration >  </ plugin > 

这样,事情应该顺利进行。 但是关于传统的足够多, Spring Boot 2.1.x可以作为完整的游戏改变者。 上下文运行程序家族ApplicationContextRunnerReactiveWebApplicationContextRunnerWebApplicationContextRunner提供了一种简单明了的方法来按每个测试方法级别定制上下文,从而使测试的执行速度非常快。

 public class LoggingConfigurationTest { private final ApplicationContextRunner runner = new ApplicationContextRunner() .withConfiguration(UserConfigurations.of(LoggingConfiguration. class ));     @Test public void loggerShouldBeSlf4j() { runner .run(ctx -> assertThat(ctx.getBean(Logger. class )).isInstanceOf(Logger. class ) ); }     @Test public void loggerShouldBeNoop() { runner .withPropertyValues( "logging.enabled=false" ) .run(ctx -> assertThat(ctx.getBean(Logger. class )).isSameAs(NOPLogger.NOP_LOGGER) ); }  } 

看起来真的很棒。 Spring Boot 2.1.x对JUnit 5.x的支持要好得多,并且即将推出的2.2 发布时, JUnit 5.x将是默认引擎 (不用担心,仍将支持旧的JUnit 4.x )。 到目前为止,切换到JUnit 5.x需要在依赖项方面进行一些工作。

 < dependency > < groupId >org.springframework.boot</ groupId > < artifactId >spring-boot-starter-test</ artifactId > < scope >test</ scope > < exclusions > < exclusion > < groupId >junit</ groupId > < artifactId >junit</ artifactId > </ exclusion > </ exclusions >  </ dependency >  < dependency > < groupId >org.junit.jupiter</ groupId > < artifactId >junit-jupiter-api</ artifactId > < scope >test</ scope >  </ dependency >  < dependency > < groupId >org.junit.jupiter</ groupId > < artifactId >junit-jupiter-engine</ artifactId > < scope >test</ scope >  </ dependency > 

作为附加步骤,您可能需要使用最新的Maven Surefire插件 ( 2.22.0或更高版本)以及现成的JUnit 5.x支持。 下面的代码段说明了这一点。

 < plugin > < groupId >org.apache.maven.plugins</ groupId > < artifactId >maven-surefire-plugin</ artifactId > < version >2.22.2</ version >  </ plugin > 

我们使用的示例配置非常幼稚,许多实际应用程序最终将具有由许多条件构建而成的非常复杂的上下文。 上下文赛跑者带来的灵活性和巨大的机会, Spring Boot 2.x测试脚手架的宝贵补充,只是活泼的救星,请紧记它们。

完整的项目资源可在Github上找到 。

翻译自: https://www.javacodegeeks.com/2019/08/testing-spring-boot-conditionals-sane-way.html

spring boot测试

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/331922.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

不相交集的求并算法(按集合大小求并+按高度求并)

【0】README 0.1&#xff09;本文总结于 数据结构与算法分析&#xff0c; 但源代码均为原创&#xff0c;旨在实现 不相交集ADT的两个操作&#xff1a;合并集合union查找集合find&#xff1b; 0.2&#xff09; 不相交集ADT 的 Introduction &#xff0c; 参见 http://blog.csd…

及时复盘的好处_该如何复盘 先来说说复盘的好处: 复盘的好处简直太多了!就像你学习一样有一个总结的过程,复盘的最直接好处就是增强你的“股感”!在股市... - 雪球...

来源&#xff1a;雪球App&#xff0c;作者&#xff1a; 孜孜金融&#xff0c;(https://xueqiu.com/3493013654/135651359)先来说说复盘的好处&#xff1a;复盘的好处简直太多了&#xff01;就像你学习一样有一个总结的过程&#xff0c;复盘的最直接好处就是增强你的“股感”&am…

posman mocks_使用Mocks进行需求驱动的软件开发

posman mocksjmock作者撰写的有关模拟框架的优秀论文 。 本文写于18年前的2004年&#xff0c;但其中有许多构建可维护软件系统的技巧。 在这篇文章中&#xff0c;我将重点介绍本文中的关键思想&#xff0c;但建议您阅读本文以获取有关模拟和编程实践的重要思想。 模拟对象是测…

不相交集合求并的路径压缩

【0】README 0.1&#xff09;本文总结于 数据结构与算法分析&#xff0c; 源代码均为原创&#xff0c; 旨在实现 对不相交集合的路径压缩操作&#xff1b; 0.2&#xff09;对求并后的集合进行路径压缩&#xff0c;目的是降低集合&#xff08;合并树&#xff09;的深度&#x…

python 动态加载与静态加载_python中的元类、静态方法、类方法,动态添加方法...

首先介绍几个概念&#xff1a;1、#所谓的静态方法就是这个方法任何类都可以调用&#xff0c;程序一加载就存在的方法2、所谓的类方法就是这个类一加载就存在的方法&#xff0c;不用实例化这个类就已经存在的方法3、所谓的元类就是创建类的类元类&#xff1a; type我们知道对象是…

flutter调用api_如何在Flutter(REST API)中进行API调用

flutter调用api在本文中&#xff0c;我们将看一下如何快速进行API调用并使用简单的REST API。 在这里查看我在Flutter上的其他一些帖子&#xff1a; Flutter vs React Native 了解Flutter中的BLoC架构 &#xff08;强烈建议&#xff09; 在Flutter中构建ListView&#xff0…

java重载与重写的区别+重写父类equals方法的完美实现

【0】README 0.1&#xff09; 本文章节【1】和【2】的内容转自 http://www.cnblogs.com/bluestorm/archive/2012/03/01/2376236.html &#xff1b; 旨在区分重载与重写以及他们的相关概念&#xff1b; 0.2&#xff09; 本文章节【3】的内容转自 http://blog.csdn.net/pacoson…

checkpoint_通过Main的Checkpoint Restore加快Java启动速度

checkpointJava虚拟机为已编译为字节码 &#xff08;但不一定是用Java编写&#xff09;的应用程序提供了托管运行时环境。 与为特定平台静态编译的代码相比&#xff0c;这为应用程序开发人员提供了许多好处&#xff0c;并且通常可以提高性能。 JVM通过垃圾回收器 &#xff08;G…

泛型数组列表ArrayList

【0】README 0.1&#xff09; 本文描述源代码均 转自 core java volume 1&#xff0c; 旨在理清 java 中的 数组列表 ArrayList&#xff1b; 【2】数组列表 ArrayList 2.1&#xff09;ArrayList&#xff1a; ArrayList 具有自动调节数组容量的功能&#xff0c; 而不需要为此…

大数据聚类分析用于预测_多模态数据中的非负矩阵分解用于分割和标签预测

引用Akata Z, Thurau C, Bauckhage C. Non-negative matrix factorization in multimodality data for segmentation and label prediction[C]. 2011.摘要随着 Internet 上带注释的多媒体数据的可用性不断提高&#xff0c;要求有一种技术可以实现不同类型数据的原则性联合处理。…

程序员 rs编码_为什么声明性编码使您成为更好的程序员

程序员 rs编码在许多情况下&#xff0c;具有功能组成的声明式解决方案提供了优于传统命令式代码的出色代码指标。 阅读本文并了解如何使用具有功能组成的声明性代码成为一名更好的程序员。 在本文中&#xff0c;我们将仔细研究三个问题示例&#xff0c;并研究用于解决这些问题…

对象包装器与自动(拆箱)装箱+参数数量可变的方法+枚举类

【0】README 0.1&#xff09; 本文描述源代码均 转自 core java volume 1&#xff0c; 旨在理解 自动拆箱&#xff08;装箱&#xff09;、printf的参数数量可变 以及 枚举类的详细说明&#xff1b; 0.2&#xff09; 源代码&#xff1a; https://github.com/pacosonTang/core…

go 监测tcp 连接断开_TCP三次握手和四次挥手以及11种状态

三次握手置位概念&#xff1a;根据TCP的包头字段&#xff0c;存在3个重要的标识ACK、SYN、FINACK&#xff1a;表示验证字段 SYN&#xff1a;位数置1&#xff0c;表示建立TCP连接 FIN&#xff1a;位数置1&#xff0c;表示断开TCP连接三次握手过程说明&#xff1a;1.由客户端发送…

java序列化深克隆_如何在内存序列化中使用Java深克隆对象

java序列化深克隆在我以前的文章中&#xff0c;我解释了深度克隆和浅层克隆之间的区别 &#xff0c; 以及复制构造函数和防御性复制方法比默认的Java克隆如何更好。 使用复制构造函数和防御性复制方法进行的Java对象克隆当然具有某些优势&#xff0c;但是我们必须显式编写一些…

java反射机制+继承设计技巧

【0】README 0.1&#xff09; 本文描述源代码均 转自 core java volume 1&#xff0c; 旨在理解 java反射机制 &#xff1b;最后还顺带提出了 继承设计的技巧&#xff1b; 【1】反射相关 1&#xff09;反射定义&#xff1a;能够分析类能力的程序称为反射&#xff1b; 2&…

60秒计时器的仿真电路_基于伏秒平衡的同步整流方案探讨

为了提高电源的效率和功率密度&#xff0c;尤其是低输出电压的应用场合&#xff0c;同步整流是不可或缺的。图1-1 反激输出二极管损耗比如上图的反激电源如果输出二极管 Vf0.7V&#xff0c;输出电压 Vout3V 则效率不会高于3/(30.7)81%。为了提升效率一般会选用低导通压降的肖特…

利用反射机制创建新类的两种方式及比较

【0】README 0.1&#xff09; 本文描述源代码均 转自 http://blog.csdn.net/fenglibing/article/details/4531033 &#xff0c; 旨在深入理解 如何利用反射机制创建类实例&#xff1b; 0.2&#xff09; 转载的源代码&#xff0c;参见 https://github.com/pacosonTang/core-ja…

如何设计高效测试用例_高效的企业测试-单元和用例测试(2/6)

如何设计高效测试用例在本系列的第一部分中&#xff0c;我们看到了有效测试应满足的一些普遍适用的原则和约束。 在这一部分中&#xff0c;我们将仔细研究代码级单元测试和组件或用例测试。 单元测试 单元测试验证单个单元&#xff08;通常是类&#xff09;的行为&#xff0c…

php mysql study_PHPstudy升级mysql数据库

首先查看phpstudy的mysql版本&#xff1a;方法一 使用mysql的version函数&#xff1a;mysql> selectversion();方法二 status命令mysql> status&#xff1b;方法三 直接在cmd下输入命令查看mysql -vmysql --help下面开始升级数据库1、备份好自己的数据库2、清空phpstudy…

selenium 等待_Selenium等待:内隐,外显,流利和睡眠

selenium 等待Selenium等待页面加载在Selenium脚本中起着重要的作用。 它们有助于使它们不易剥落&#xff0c;更可靠。 Selenium提供多次等待&#xff0c;以根据某些条件在脚本执行中提供足够的等待或暂停。 从而确保您在使用Selenium执行自动化测试时不会导致脚本失败。 在本教…