Archunit 理解及调研
背景
-
通过单元测试的形式规范代码编写
-
Archunit是一个免费、简单、可扩展的类库,用于检查Java代码的体系结构。提供检查包和类的依赖关系、调用层次和切面的依赖关系、循环依赖检查等其他功能。它通过导入所有类的代码结构,基于Java字节码分析实现这一点。
使用
方法一:
- 添加maven依赖
<dependency>
<groupId>com.tngtech.archunit</groupId>
<artifactId>archunit</artifactId>
<version>0.15.0</version>
<scope>test</scope>
</dependency>
- 增加Archunit单元测试
- 规则编写 规格的语法:确定操作的数据(包\类\方法) - 断言
@SpringBootTest
public class ArchUnitTest {
@Test
public void controller_need_end_with_controller() {
JavaClasses classes = new ClassFileImporter()
.withImportOption(ImportOption.Predefined.DO_NOT_INCLUDE_JARS)
.withImportOption(ImportOption.Predefined.DO_NOT_INCLUDE_TESTS)
.importPackages("com.miya.hh.item");
//1. controller后缀名校验
classes().that().resideInAPackage("..controller..").should().haveSimpleNameEndingWith("Controller").check(classes);
// 1.1 controller结尾的类应该在controller包下,并有@RestController、@RequestMapping
classes().that().haveSimpleNameEndingWith("Controller").should().resideInAPackage("..controller").andShould().beAnnotatedWith(RestController.class).andShould().beAnnotatedWith(RequestMapping.class).check(classes);
//2. service 后缀名校验
classes().that().resideInAPackage("..service").should().haveSimpleNameEndingWith("Service").check(classes);
//3. service.impl 注解&后缀名校验
classes().that().resideInAPackage("..service.impl").should().beAnnotatedWith("Service").andShould().haveSimpleNameEndingWith("ServiceImpl").check(classes);
//4. 数据操作类需要注解 @Mapper
classes().that().resideInAPackage("..mapper..").and().haveSimpleNameEndingWith("Mappler").should().beAnnotatedWith(Mapper.class).check(classes);
//5. 实体后缀名校验
classes().that().resideInAPackage("..data").should().haveSimpleNameEndingWith("DO").check(classes);
//6. 禁止循环依赖 slices().matching("com.miya.hh.item.(*)..").should().beFreeOfCycles();
// 不应该使用System.*
NO_CLASSES_SHOULD_ACCESS_STANDARD_STREAMS.check(classes);
}
}
方法二:
- 添加maven依赖
<dependency>
<groupId>com.tngtech.archunit</groupId>
<artifactId>archunit-junit5</artifactId>
<version>0.15.0</version>
<scope>test</scope>
</dependency>
- 示例
@AnalyzeClasses(packages = "com.miya.hh.item", importOptions = {ImportOption.DoNotIncludeJars.class, ImportOption.DoNotIncludeTests.class})
public class ArchUnitTest5 {
/**
* DO需要放在data文件下
*/
@ArchTest
private static ArchRule pojo_need_in_data = classes().that().haveNameMatching(".*DO").should()
.resideInAPackage("..data..").as("pojo should reside in a package '..data..'");
/**
* 设置统一的返回
*/
@ArchTest
private static ArchRule controller_nee_return_result = methods().that().areDeclaredInClassesThat().resideInAPackage("..controller..").and().arePublic()
.should().haveRawReturnType(Result.class).because("this project requires a uniform return");
}
关键名词解释
| 词汇 | 解释 |
|---|---|
| class() | 需要定位的类 |
| method() | 需要定位的方法 |
| layer() | 需要定位的包 |
**未完....待续**