Archunit 理解及调研

2,440 阅读2分钟

Archunit 理解及调研

背景

  1. 通过单元测试的形式规范代码编写

  2. Archunit是一个免费、简单、可扩展的类库,用于检查Java代码的体系结构。提供检查包和类的依赖关系、调用层次和切面的依赖关系、循环依赖检查等其他功能。它通过导入所有类的代码结构,基于Java字节码分析实现这一点。

使用

方法一:

  1. 添加maven依赖
<dependency>
    <groupId>com.tngtech.archunit</groupId>
    <artifactId>archunit</artifactId>
    <version>0.15.0</version>
    <scope>test</scope>
</dependency>
  1. 增加Archunit单元测试

  1. 规则编写 规格的语法:确定操作的数据(包\类\方法) - 断言
@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);

    }
}

方法二:

  1. 添加maven依赖
		<dependency>
			<groupId>com.tngtech.archunit</groupId>
			<artifactId>archunit-junit5</artifactId>
			<version>0.15.0</version>
			<scope>test</scope>
		</dependency>
  1. 示例
@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()需要定位的包

**未完....待续**
  1. ArchUnit-Examples
  2. ArchUnit 官网