JUnit5中扩展模型的深入理解java

JUnit5=JUnitPlatform+JUnitJupiter+JUnitVintage

这看上去比Junit4复杂,实际上在导入包时也会复杂一些。

JUnitPlatform是在JVM上启动测试框架的基础。

JUnitJupiter是JUnit5扩展的新的编程模型和扩展模型,用来编写测试用例。Jupiter子项目为在平台上运行Jupiter的测试提供了一个TestEngine(测试引擎)。

JUnitVintage提供了一个在平台上运行JUnit3和JUnit4的TestEngine。

关键要点

JUnit是最受欢迎的基于JVM的测试框架,在第5个主要版本中进行了彻底的改造。JUnit5提供了丰富的功能——从改进的注解、标签和过滤器到条件执行和对断言消息的惰性求值。这让基于TDD编写单元测试变得轻而易举。新框架还带来了一个强大的扩展模型。扩展开发人员可以使用这个新模型向JUnit5中添加自定义功能。本文将指导你完成自定义扩展的设计和实现。这种自定义扩展机制为Java程序员提供了一种创建和执行故事和行为(即BDD规范测试)的方法。

我们首先使用JUnit5和我们的自定义扩展(称为“StoryExtension”)来编写一个示例故事和行为(测试方法)。这个示例使用了两个新的自定义注解“@Story”和“@Scenario”,以及“Scene”类,用以支持我们的自定义StoryExtension:

importorg.junit.jupiter.api.extension.ExtendWith;importud.junit.bdd.ext.Scenario;importud.junit.bdd.ext.Scene;importud.junit.bdd.ext.Story;importud.junit.bdd.ext.StoryExtension;@ExtendWith(StoryExtension.class)@Story(name=“Returnsgobacktothestockpile”,description=“...“)publicclassStoreFrontTest{@Scenario(“Refundeditemsshouldbereturnedtothestockpile”)publicvoidrefundedItemsShouldBeRestocked(Scenescene){scene.given(“customerboughtabluesweater”,()->buySweater(scene,“blue”)).and(“Ihavethreebluesweatersinstock”,()->assertEquals(3,sweaterCount(scene,“blue”),“Storeshouldcarry3bluesweaters”)).when(“thecustomerreturnsthebluesweaterforarefund”,()->refund(scene,1,“blue”)).then(“Ishouldhavefourbluesweatersinstock”,()->assertEquals(4,sweaterCount(scene,“blue”),“Storeshouldcarry4bluesweaters”)).run();}}从代码片段中我们可以看到,Jupiter的扩展模型非常强大。我们还可以看到,我们的自定义扩展及其相应的注解为测试用例编写者提供了简单而干净的方法来编写BDD规范。

作为额外的奖励,当使用我们的自定义扩展程序执行测试时,会生成如下所示的文本报告:

STORY:ReturnsgobacktothestockpileAsastoreowner,inordertokeeptrackofstock,Iwanttoadditemsbacktostockwhenthey'rereturned.SCENARIO:RefundeditemsshouldbereturnedtostockGIVENthatacustomerpreviouslyboughtabluesweaterfrommeANDIhavethreebluesweatersinstockWHENthecustomerreturnsthebluesweaterforarefundTHENIshouldhavefourbluesweatersinstock

这些报告可以作为应用程序功能集的文档。

自定义扩展StoryExtension能够借助以下核心概念来支持和执行故事和行为:

注解

示例中的“@ExtendWith”注解是由Jupiter提供的标记接口。这是在测试类或方法上注册自定义扩展的方法,目的是让Jupiter测试引擎调用给定类或方法的自定义扩展。或者,测试用例编写者可以通过编程的方式注册自定义扩展,或者通过服务加载器机制进行自动注册。

我们的自定义扩展需要一种识别故事的方法。为此,我们定义了一个名为“Story”的自定义注解类,如下所示:

importorg.junit.platform.commons.annotation.Testable;@Testablepublic@interfaceStory{...}测试用例编写者应该使用这个自定义注解将测试类标记为故事。请注意,这个注解本身使用了JUnit5内置的“@Testable”注解。这个注解为IDE和其他工具提供了一种识别可测试的类和方法的方式——也就是说,带有这个注解的类或方法可以通过JUnit5Jupiter测试引擎来执行。

我们的自定义扩展还需要一种方法来识别故事中的行为或场景。为此,我们定义一个名为“Scenario”的自定义注解类,看起来像这样:

importorg.junit.jupiter.api.Test;@Testpublic@interfaceScenario{...}测试用例编写者应使用这个自定义注解将测试方法标记为场景。这个注解本身使用了JUnit5Jupiter的内置“@Test”注解。当IDE和测试引擎扫描给定的一组测试类并在公共实例方法上找到@Scenario注解时,就会将这些方法标记为可执行的测试方法。

请注意,与JUnit4的@Test注解不同,Jupiter的@Test注解不支持可选的“预期”异常和“超时”参数。Jupiter的@Test注解是从头开始设计的,并考虑到了可扩展性。

生命周期

扩展开发者可以自由地实现所有或部分生命周期接口。

“BeforeAllCallback”接口提供了一种方法用于初始化扩展并在调用JUnit测试容器中的测试用例之前添加自定义逻辑。我们的StoryExtension类将实现这个接口,以确保给定的测试类使用了“@Story”注解。

importorg.junit.jupiter.api.extension.BeforeAllCallback;publicclassStoryExtensionimplementsBeforeAllCallback{@OverridepublicvoidbeforeAll(ExtensionContextcontext)throwsException{if(!AnnotationSupport.isAnnotated(context.getRequiredTestClass(),Story.class)){thrownewException(“Use@Storyannotation...“);}}}Jupiter引擎将提供一个用于运行扩展的执行上下文。我们使用这个上下文来确定正在执行的测试类是否使用了“@Story”注解。我们使用JUnit平台提供的AnnotationSupport辅助类来检查是否存在这个注解。

自定义扩展可以使用存储来保存和获取任意数据——基本上就是一个存在于内存中的map。为了避免多个扩展之间出现意外的key冲突,JUnit引入了命名空间的概念。命名空间是一种对不同扩展保存的数据进行隔离的方法。用于隔离扩展数据的一种常用方法是使用自定义扩展类名:

privatestaticfinalNamespaceNAMESPACE=Namespace.create(StoryExtension.class);我们的扩展需要用到的另一个自定义注解是“@Scenario”注解。这个注解用于将测试方法标记为故事中的场景或行为。我们的扩展将解析这些场景,以便将它们作为JUnit测试用例来执行并生成报告。回想一下我们之前看到的生命周期图中的“BeforeEachCallback”接口,在调用每个测试方法之前,我们将使用回调来添加附加逻辑:

importorg.junit.jupiter.api.extension.BeforeEachCallback;publicclassStoryExtensionimplementsBeforeEachCallback{@OverridepublicvoidbeforeEach(ExtensionContextcontext)throwsException{if(!AnnotationSupport.isAnnotated(context.getRequiredTestMethod(),Scenario.class)){thrownewException(“Use@Scenarioannotation...“);}}}如前所述,Jupiter引擎将提供一个用于运行扩展的执行上下文。我们使用上下文来确定正在执行的测试方法是否使用了“@Scenario”注解。

回到本文的开头,我们提供了一个故事的示例代码,我们的自定义扩展负责将“Scene”类的实例注入到每个测试方法中。Scene类让测试用例编写者能够使用“given”、“then”和“when”等步骤来定义场景(行为)。Scene类是我们自定义扩展的中心单元,它包含了特定于测试方法的状态信息。状态信息可以在场景的各个步骤之间传递。我们使用“BeforeEachCallback”接口在调用测试方法之前准备一个Scene实例:如前所述,Jupiter引擎将提供一个用于运行扩展执行上下文。我们使用上下文来确定正在执行的测试方法是否使用了“@Scenario”注解。

动态参数解析

现在我们还缺少一个东西,即如何将场景实例注入到测试方法中。Jupiter的扩展模型为我们提供了一个“ParameterResolver”接口。这个接口为测试引擎提供了一种方法,用于识别希望在测试执行期间动态注入参数的扩展。我们需要实现这个接口的两个方法,以便注入我们的场景实例:

最后,为了在执行完所有故事和场景后生成报告,自定义扩展实现了“AfterAllCallback”接口:

importorg.junit.jupiter.api.extension.AfterAllCallback;publicclassStoryExtensionimplementsAfterAllCallback{@OverridepublicvoidafterAll(ExtensionContextcontext)throwsException{newStoryWriter(getStoryDetails(context)).write();}}“StoryWriter”是一个自定义类,可生成报告并将其保存到JSON或文本文件中。

现在,让我们看看如何使用这个自定义扩展来编写BDD风格的测试用例。Gradle4.6及更高版本支持使用JUnit5运行单元测试。你可以使用build.gradle文件来配置JUnit5。

dependencies{testCompilegroup:“ud.junit.bdd”,name:“bdd-junit”,version:“0.0.1-SNAPSHOT”testCompilegroup:“org.junit.jupiter”,name:“junit-jupiter-api”,version:“5.2.0"testRuntimegroup:“org.junit.jupiter”,name:“junit-jupiter-engine”,version:“5.2.0”}test{useJUnitPlatform()}如你所见,我们通过“useJUnitPlatform()”方法要求gradle使用JUnit5。然后我们就可以使用StoryExtension类来编写测试用例。这是本文开头给出的示例:

importorg.junit.jupiter.api.extension.ExtendWith;importud.junit.bdd.ext.Scenario;importud.junit.bdd.ext.Story;importud.junit.bdd.ext.StoryExtension;@ExtendWith(StoryExtension.class)@Story(name=“Returnsgobacktothestockpile”,description=“...“)publicclassStoreFrontTest{@Scenario(“Refundeditemsshouldbereturnedtothestockpile”)publicvoidrefundedItemsShouldBeRestocked(Scenescene){scene.given(“customerboughtabluesweater”,()->buySweater(scene,“blue”)).and(“Ihavethreebluesweatersinstock”,()->assertEquals(3,sweaterCount(scene,“blue”),“Storeshouldcarry3bluesweaters”)).when(“thecustomerreturnsthebluesweaterforarefund”,()->refund(scene,1,“blue”)).then(“Ishouldhavefourbluesweatersinstock”,()->assertEquals(4,sweaterCount(scene,“blue”),“Storeshouldcarry4bluesweaters”)).run();}}我们可以通过“gradletestClasses”来运行测试,或者使用其他支持JUnit5的IDE。除了常规的测试报告外,自定义扩展还为所有测试类生成BDD文档。

THE END
1.八字算命精准测算方法免费算命免费算命姓名姻缘配对八字算命是中华传统文化中的一种古老方法,通过分析一个人的出生年、月、日、时四个要素来预测其命运和性格。随着科技的发展,现在也有很多八字算命软件和网站可以进行精准测算。下面就让我们一起来了解一下八字算命精准测算方法吧! 八字算命中最重要的就是“八字排盘”。在八字排盘过程中,需要根据用户的出生年月日时等http://www.zgxwzx.com.cn/mfsm/33882.html
2.如何测什么命最准的测命方法如何测什么命 最准的测命方法 在这个瞬息万变的时代,很多人都渴望了解自己的命运,以便做出更好的决策,追寻理想的生活。命理学,作为一门古老而神秘的学问,给了我们洞察自我的机会。那么,如何测什么命?本文将带您深入探讨这个引人入胜的话题。 命运的起源:了解命理学http://www.juicychina.net/view/57483
3.测命运最准的方法,网上名字测分准不准每个人都想知道自己的命运,了解自己的性格特点和未来的走向。现在,有很多方法可以帮助我们了解自己的命运,其中一种比较流行的方法是测名字。但网上名字测分到底准不准呢?本文从四个方面详细阐述了测命运最准的方法,让读者更加了解这个话题。 一、姓名学基础 http://www.yisuanyuan.com/a/254113.html
4.来看看印度人是如何测命的提起印度,除了扑面而来的咖喱味儿,你还会想到什么? 重新加载 挂满了人的火车? 重新加载 还是全民开挂的种族天赋? 讲真的,每次一听到有关隔壁三哥的故事,身处在东方小孟买的鲲都会被强制刷新一波三观。 而作为一名职业命理师,鲲当然也会时不时地去了解一些来自世界各地不同的占卜测命方法。这不,最近印度玄学又成功https://www.douban.com/note/736249501/
5.生辰八字算命八字算命八字预测八字算命可以算什么 批八字算命一生命运 八字看命中注定的配偶 八字算命2022年流年运势 八字算命婚姻免费测试 生辰八字喜用神查询表 八字看十大贵命命格 八字测你命带多少桃花 免费八字测姻缘何时到 八字测未来另一半的长相性格 生辰八字一生事业算命 起名字2024免费八字起名 https://bz.99166.com/
6.文献阅读笔记:SmartHomesthatMonitorBreathingandHeartRateVR是无线系统,需要最小信噪比SNR来从噪声中提取信号。最大距离为8m,距离越远,信噪比越低 3.准静态需求 全身运动引起的信号变化会覆盖生命体征引起的微小变化 4.非人类的运动 风扇不会影响,宠物会被识别为受测者 9. Conclusion and Future Opportunitieshttps://blog.csdn.net/chiyue_mio/article/details/120761775
7.真正的免费测名字八字最准,免费算命姓名测试打分真正的免费测名字八字最准 2021年姓名八字评分测算,名字测试打分最准确生辰八字 2024-11-17 提起2021年姓名八字评分测算,大家都知道,有人问名字测试打分最准确生辰八字,另外,还有人想问八字测测2021年运势?你知道这是怎么回事?其实汪志达 姓名八字吉凶评分测算,下面就一起来看看名字测试打分最准确生辰八字,希望能够帮助http://www.jsfctech.com/yx/7558u/
8.预测命运最准的方法理想股票技术论坛想要找到最准确的方法来预测自己的命运吗?我们提供一系列科学有效的方法,帮助您选择合适的方法,并准确地预测自己的命运。不管是通过基于股票技术分析的指标公式,还是借助精通股票基本面的知识,我们都将为您提供有关命运预测的专业指导和建议。立即开始,掌握预测命运的https://www.55188.com/tag-02357901.html
9.姓名测试打分免费测名字打分起名字测试打分算命姓名测试打分 (姓名网 xingming.com),最准的名字打分免费测试,内容包括:名字测试打分,生辰八字算命,姓名打分,姓名缘分配对,宝宝起名打分测试,姓名爱情测试,生肖运程等,周易姓名测分,名字打分100等测算内容。https://m.xingming.com/
10.生命体征的测量方法及注意事项合集(一)测体温的注意事项: 欧阳历创编 2021..02.09 欧阳历创编 2021..02.09 1、根据病人的病情、自理程度选择合适的测温方法及 部位。婴幼儿,昏迷、精神异常、口鼻手术、不合作者、 呼吸困难不用口表测量温度;测腋表时要擦干腋窝,极度 消瘦的病人不用腋表测温;腹泻、直肠或肛门手术,心肌 梗死患者不宜用直肠测温法。https://wenku.baidu.com/aggs/eba5a50216fc700abb68fca5.html
11.公开2024龙年清宫图正版生男生女表!超准的性别计算公式详解测量孩子出生最准确的科学方法 民间流传的各种测胎儿性别的方法,很多都是从前人的经验中总结出来的,并没有经过科学的验证,所以不可信,只有用科学的方法来鉴定胎儿的性别,才是最准确可靠的。目前我国禁止医院鉴定胎儿性别,其实生男生女都是好的,宝宝的健康才是最重要的。 https://www.snsnb.com/zt/show-2522.html
12.崇道命理网算命大师真人在线算命生辰八字算命崇道命理网,算卦街真人算命一条街,算命大师,在线算命,网上算命,网络算命,网上算卦,周易算命网,天地和命理网,易灵,真人算命,免费算命网,算命网,算命最准的网站,算命网站,最准算命网,周易算命网,算命大师在线咨询,命理网,每日财运。https://www.ffxlzx.com/
13.寿命检测范文7篇(全文)3.2 预测方法 3.2.1 最小允许壁厚确定 根据美国ASME锅炉压力容器N-480《管道腐蚀减薄验收准则》进行评定。该准则规定对腐蚀管道评定的范围必须满足以下条件:0.3t≤tp≤0.875t式中[2], t为正常时管道的壁厚, 即原设计时无腐蚀的壁厚;tp为评定寿命时的最大腐蚀坑深度剩余壁厚, 即最小允许壁厚。 https://www.99xueshu.com/w/ikeyqd7dj8c3.html