使用ArchUnit验证代码和体系结构约束
介绍
ArchUnit是一个用于根据一组自定义代码和体系结构约束检查Java代码的库。 这些约束可以在单元测试中的流畅Java API中定义。 ArchUnit可用于验证类或层之间的依赖关系,检查循环依赖关系等等。 在本文中,我们将创建一些示例规则,以了解如何从ArchUnit中受益。
必需的依赖
要使用ArchUnit,我们需要在项目中添加以下依赖项:
< dependency > < groupId >com.tngtech.archunit</ groupId > < artifactId >archunit-junit5</ artifactId > < version >0.13.0</ version > < scope >test</ scope > </ dependency >
如果您仍在使用JUnit 4,则应改用archunit-junit4构件。
创建第一个ArchUnit规则
现在,我们可以开始创建第一个ArchUnit规则。 为此,我们在测试文件夹中创建一个新类:
@RunWith (ArchUnitRunner. class ) //only for JUnit 4, not needed with JUnit 5 @AnalyzeClasses (packages = "com.mscharhag.archunit" ) public class ArchUnitTest { // verify that classes whose name name ends with "Service" should be located in a "service" package @ArchTest private final ArchRule services_are_located_in_service_package = classes() .that().haveSimpleNameEndingWith( "Service" ) .should().resideInAPackage( "..service" ); }
通过@AnalyzeClasses,我们告诉ArchUnit应该分析哪些Java软件包。 如果使用的是JUnit 4,则还需要添加ArchUnit JUnit运行器。
在类内部,我们创建一个字段并使用@ArchTest对其进行注释。 这是我们的第一个测试。
我们可以使用ArchUnits流畅的Java API定义要验证的约束。 在此示例中,我们要验证所有名称以Service结尾的类(例如UserService )都位于名为service (例如foo.bar.service )的包中。
大多数ArchUnit规则都以选择器开头,该选择器指示应验证哪种类型的代码单元(类,方法,字段等)。 在这里,我们使用静态方法classes()选择类。 我们使用that()方法将选择范围限制为类的子集(这里我们仅选择名称以Service结尾的类)。 使用should()方法,我们可以定义与所选类匹配的约束(此处:这些类应位于服务包中)。
运行此测试类时,将执行所有带有@ArchTest注释的测试。 如果ArchUnits在服务包之外检测到服务类,则测试将失败。
更多例子
让我们看一些更多的例子。
我们可以使用ArchUnit来确保所有Logger字段都是私有,静态和最终的:
// verify that logger fields are private, static and final @ArchTest private final ArchRule loggers_should_be_private_static_final = fields() .that().haveRawType(Logger. class ) .should().bePrivate() .andShould().beStatic() .andShould().beFinal();
在这里,我们选择Logger类型的字段,并在一个规则中定义多个约束。
或者,我们可以确保实用程序类中的方法必须是静态的:
// methods in classes whose name ends with "Util" should be static @ArchTest static final ArchRule utility_methods_should_be_static = methods() .that().areDeclaredInClassesThat().haveSimpleNameEndingWith( "Util" ) .should().beStatic();
为了强制名为impl的软件包不包含任何接口,我们可以使用以下规则:
// verify that interfaces are not located in implementation packages @ArchTest static final ArchRule interfaces_should_not_be_placed_in_impl_packages = noClasses() .that().resideInAPackage( "..impl.." ) .should().beInterfaces();
请注意,我们使用noClasses()而不是classes()来抵消should约束。
(我个人认为,如果我们可以将规则定义为interfaces()。should()。notResideInAPackage(“ .. impl ..”),则该规则将更容易阅读。不幸的是,ArchUnit不提供interfaces()方法)
也许我们正在使用Java Persistence API并希望确保EntityManager仅在存储库类中使用:
@ArchTest static final ArchRule only_repositories_should_use_entityManager = noClasses() .that().resideOutsideOfPackage( "..repository" ) .should().dependOnClassesThat().areAssignableTo(EntityManager. class );
分层架构示例
ArchUnit还附带了一些实用程序,用于验证特定的体系结构样式。
例如,我们可以使用layeredArchitecture()来验证分层体系结构中各层的访问规则:
@ArchTest static final ArchRule layer_dependencies_are_respected = layeredArchitecture() .layer( "Controllers" ).definedBy( "com.mscharhag.archunit.layers.controller.." ) .layer( "Services" ).definedBy( "com.mscharhag.archunit.layers.service.." ) .layer( "Repositories" ).definedBy( "com.mscharhag.archunit.layers.repository.." ) .whereLayer( "Controllers" ).mayNotBeAccessedByAnyLayer() .whereLayer( "Services" ).mayOnlyBeAccessedByLayers( "Controllers" ) .whereLayer( "Repositories" ).mayOnlyBeAccessedByLayers( "Services" );
在这里,我们定义了三层:控制器,服务和存储库。 存储库层只能由服务层访问,而服务层只能由控制器访问。
通用规则的快捷方式
为了避免我们必须自己定义所有规则,ArchUnit附带了一组定义为静态常量的通用规则。 如果这些规则符合我们的需求,我们可以简单地将它们分配给测试中的@ArchTest字段。
例如,如果我们确保没有抛出Exception和RuntimeException类型的异常,则可以使用预定义的NO_CLASSES_SHOULD_THROW_GENERIC_EXCEPTIONS规则:
@ArchTest private final ArchRule no_generic_exceptions = NO_CLASSES_SHOULD_THROW_GENERIC_EXCEPTIONS;
摘要
ArchUnit是一个强大的工具,可以根据一组自定义规则来验证代码库。 常见的静态代码分析工具(例如FindBugs或SonarQube)也报告了我们看到的一些示例。 但是,这些工具通常很难根据您自己的项目特定规则进行扩展,这就是ArchUnit的用武之地。
与往常一样,您可以从GitHub上的示例中找到Sources。 如果您对ArchUnit感兴趣,还应该查看全面的用户指南 。
翻译自: https://www.javacodegeeks.com/2020/02/validating-code-and-architecture-constraints-with-archunit.html
使用ArchUnit验证代码和体系结构约束相关推荐
- FPGA之道(64)代码中的约束信息(一)保持约束
文章目录 前言 HDL中的常用约束示例 保持约束 keep keep_hierarchy 前言 这一节的内容很有意思也很有用,对于我们主动地操作我们的Verilog代码很有帮助.众所周知,通过设置工具 ...
- 使用代码创建AutoLayout约束
使用代码创建AutoLayout约束 1.代码创建约束的步骤 2.代码创建约束的常用方法 3.代码创建约束的原则 4.禁用Autoresizing的原因 5. 设置相对状态栏的约束,使用self.to ...
- oracle建表代码,Oracle 建表(一对多)代码及相关约束示例
建表(一对多)代码及相关约束 create table t_class( c_id number(3) primary key, c_name varchar2(20) not null ); cre ...
- 国产自主可控的形式化验证代码自动生成工具ModelCoder可替代Matlab/Sumlink
在安全关键领域,基于模型的软件工程或者软件开发已逐渐进入了我国的装备研制过程中.使用SimuLink或者SCADE等嵌入式软件建模工具对算法或者控制逻辑进行可视化建模,然后生成高可靠的二进制代码逐渐成 ...
- element-UI框架使用validate.js的form校验规则(+自定义验证代码)- 应用篇
文章目录 element-UI除了官方给出的校验规则,还可以自定义(举例如下) 代码示例: 参考文章: element-UI除了官方给出的校验规则,还可以自定义(举例如下) element-UI框架f ...
- 利用strut2标签自动生成form前端验证代码
利用strut2标签自动生成form前端验证代码,使用到的技术有 1.struts2标签,如<s:form> <s:textfieled> 2.struts2读取*Valida ...
- 解决视图状态消息验证代码 (MAC) 错误
https://blog.csdn.net/bingtingabc/article/details/49148745 2015年10月15日 10:05:56 bingtingabc 阅读数:3397 ...
- PHP修复输入验证代码中的漏洞
聚焦源代码安全,网罗国内外最新资讯! 编译:代码卫士 如果你在使用PHP,检查下是否是最新版本 8.1.3.上周,PHP 发布该版本,修复了多个内存管理不当漏洞,其中一个漏洞是 CVE-2021-2 ...
- php 判断是否ipv6,PHP IPV6正则表达式验证代码
PHP IPV6正则表达式验证代码 发布于 2014-10-21 21:58:01 | 117 次阅读 | 评论: 0 | 来源: 网友投递 PHP开源脚本语言PHP(外文名: Hypertext P ...
最新文章
- 卷积神经网络的一些规则
- JAVA SE学习day_04:RandomAccessFile
- intel lock汇编指令保障有序性
- 【2016年第6期】面向国际的生命组学大数据管理体系建设
- unix设置线程优先级-转
- SpringCloud实战(三)集成Open-Feign实现远程⽅法调⽤
- Cookie与Session的区别-总结很好的文章
- Java 复制PDF文档
- 计算机上有哪些操作系统?
- 老电脑重装Linux系统
- mysql多条语句union_Mysql同时执行多个select语句——union
- 蓝牙与计算机无法建立连接,电脑蓝牙无法建立连接是为什么呀?
- 《TCP/IP详解》中文版下载地址
- 电脑连不上网显示dns服务器不可用,电脑连不上网疑难解答显示DNS服务器可能不可用该怎么办...
- 考试报名管理系统C语言顺序表,学生信息管理系统(顺序表)实验
- day 09--函数和模块
- CST入门——边界条件Boundary的选择与设置
- 【无标题】C语言 最简单的代码
- 笔记本电脑无法连接WLAN网络(适配器Intel(R) Wireless-AC 9461 ) 错误代码10
- python画函数图像网格_使用opencv python在图像上绘制网格线
热门文章
- bzoj2111,P2606-[ZJOI2010]排列计数【Lucas,组合计数,dp】
- 【jzoj】2018.2.5NOIP普及组——C组模拟赛
- 【队列】Team Queue(luogu-UVA540/poj 2259)
- linux下离线安装gcc
- JfreeChart(八)之甘特图
- vue-beauty UI库
- 常用数据库连接池 (DBCP、c3p0、Druid) 配置说明
- Java 线程池框架核心代码分析
- SpringCache与Redis
- mybatis三种(查询,参数传递)