如何使用ArchUnit测试Java项目的体系结构

by Emre Savcı

由EmreSavcı

如何使用ArchUnit测试Java项目的体系结构 (How to test your Java project’s architecture with ArchUnit)

In this post, I will show you an interesting library called ArchUnit that I met recently. It does not test your code flow or business logic. The library lets you test your “architecture” including class dependencies, cyclic dependencies, layer accesses, naming conventions, and inheritance checking.

在这篇文章中,我将向您展示我最近遇到的一个有趣的库ArchUnit。 它不会测试您的代码流或业务逻辑。 该库使您可以测试“体系结构”,包括类依赖关系,循环依赖关系,图层访问,命名约定和继承检查。

Here is the list of tests which we will write in this post:

这是我们将在本文中编写的测试列表:

  • Cyclic Dependency Test

    循环依赖测试
  • Layer Access Test

    层访问测试
  • Class Location Test

    课堂位置测试
  • Method Return Type Test

    方法返回类型测试
  • Naming Convention Test

    命名约定测试

So let's imagine a project with the package structure shown below:

因此,让我们想象一个具有如下所示的包结构的项目:

Before writing tests for our architecture, as a start point, we decide that our controllers should not be accessed from any other class or package. Also conceptually we accept that controller names should end with the “…Controller” suffix.

首先,为我们的体系结构编写测试之前,我们决定不应从任何其他类或程序包访问控制器。 同样从概念上讲,我们接受控制器名称应以“ ... Controller”后缀结尾。

Now it is time to get our hands dirty. Below, we start writing our first test. It allows us to check our naming convention.

现在是时候弄脏我们的手了。 下面,我们开始编写我们的第一个测试。 它使我们可以检查我们的命名约定。

命名约定测试 (Naming Convention Tests)

@RunWith(ArchUnitRunner.class)@AnalyzeClasses(packages = "com.test.controllers")public class NamingConventionTests {    @ArchTest    ArchRule controllers_should_be_suffixed = classes()            .that().resideInAPackage("..controllers..")            .should().haveSimpleNameEndingWith("Controller");    }

When we run the test we see that it passes:

当我们运行测试时,我们看到它通过了:

There are two types of tests with arc unit. One of them is like the one shown above. If we want, we can write tests using JUnit's Test annotation. Change the RunWith parameter to JUnit4.class and remove the AnalyzeClasses annotation.

电弧单元有两种测试类型。 其中之一就像上面显示的那样。 如果需要,可以使用JUnit的Test批注编写测试。 将RunWith参数更改为JUnit4.class并删除AnalyzeClasses批注。

In this way, we specify the packages to import using ClassFileImporter within ArcUnit.

通过这种方式,我们在ArcUnit中指定使用ClassFileImporter导入的包。

@RunWith(JUnit4.class)public class NamingConventionTests {    @Test    public void controllers_should_be_suffixed() {        JavaClasses importedClasses = new ClassFileImporter().importPackages("com.test.controllers");        ArchRule rule = classes()                .that().resideInAPackage("..controllers..")                .should().haveSimpleNameEndingWith("Controller");        rule.check(importedClasses);    }}

Now, let's see what happens if we have a different suffix. Change ("Controller") to ("Ctrl") and run:

现在,让我们看看如果使用不同的后缀会发生什么。 将("Controller") to ("Ctrl")更改("Controller") to ("Ctrl")并运行:

The exception says that: “java.lang.AssertionError: Architecture Violation [Priority: MEDIUM] — Rule ‘classes that reside in a package ‘..controllers..’ should have a simple name ending with ‘Ctrl’’ was violated (1 time):the simple name of com.test.controllers.FirstController does not end with ‘Ctrl’ in (FirstController.java:0)”

异常表示:“ java.lang。 AssertionError违反体系结构 [优先级:中]- 违反了规则'类,位于包'..controllers ..'中,其简单名称以'Ctrl'结尾(1次):com.test的简单名称.controllers。 FirstController在(FirstController.java:0) 中不以'Ctrl'结尾

So far so good. We wrote our first test and it correctly runs. Now it’s time to jump to other tests.

到目前为止,一切都很好。 我们编写了第一个测试,它可以正确运行。 现在该跳到其他测试了。

课堂位置测试 (Class Location Tests)

Let's write another rule that makes sure that classes which have annotation repositories should be located in the infrastructure package.

让我们编写另一条规则,以确保具有批注存储库的类应位于基础结构包中。

@RunWith(ArchUnitRunner.class)@AnalyzeClasses(packages = "com.test")public class RepositoryPackageTest {    @ArchTest    public ArchRule repositories_should_located_in_infrastructure = classes()            .that().areAnnotatedWith(Repository.class)            .should().resideInAPackage("..infrastructure..");}

If we annotate other classes than infrastructure packages, the test raises an AssertionError.

如果我们注释除基础结构软件包以外的其他类,则测试将引发AssertionError。

方法返回类型测试 (Method Return Type Tests)

Let's write some method checks. Suppose we decide that our controller methods should return a type BaseResponse.

让我们编写一些方法检查。 假设我们决定控制器方法应返回BaseResponse类型。

@RunWith(ArchUnitRunner.class)@AnalyzeClasses(packages = "com.test.controllers")public class ControllerMethodReturnTypeTest {    @ArchTest    public ArchRule controller_public_methods_should_return = methods()            .that().areDeclaredInClassesThat().resideInAPackage("..controllers..")            .and().arePublic()            .should().haveRawReturnType(BaseResponse.class)            .because("here is the explanation");}

循环依赖测试 (Cyclic Dependency Tests)

In this day and age, cyclic dependency issues are handled by most of the IOC containers. It is a good thing to have some tool that tests it for us.

在当今时代,大多数IOC容器都处理周期性依赖问题。 拥有一些可以为我们测试它的工具是一件好事。

Now first create classes that have cyclic complexity:

现在,首先创建具有循环复杂性的类:

package com.test.services.slice1;import com.test.services.slice2.SecondService;public class FirstService {    private SecondService secondService;    public FirstService() {        this.secondService = new SecondService();    }}
package com.test.services.slice2;import com.test.services.slice1.FirstService;public class SecondService {    private FirstService firstService;    public SecondService() {        this.firstService = new FirstService();    }}

FirstService and SecondService depend on each other, and it creates the cycle.

FirstService和SecondService相互依赖,并创建周期。

Now write a test for it:

现在为它编写一个测试:

@RunWith(ArchUnitRunner.class)@AnalyzeClasses(packages = "com.test")public class CyclicDependencyTest {    @ArchTest    public static final ArchRule rule = slices().matching("..services.(*)..")            .should().beFreeOfCycles();}

Running this test gives the below result:

运行此测试将得出以下结果:

Also, the result is the same as constructor injection.

而且,结果与构造函数注入相同。

层测试 (Layer Tests)

Now it is time to write a layer test which covers our layers.

现在是时候编写覆盖我们各层的层测试了。

@RunWith(JUnit4.class)public class LayeredArchitectureTests {    @Test    public void layer_dependencies_are_respected() {        JavaClasses importedClasses = new ClassFileImporter().importPackages("..com.test..");        ArchRule myRule = layeredArchitecture()                .layer("Controllers").definedBy("..com.test.controllers..")                .layer("Services").definedBy("..com.test.services..")                .layer("Infrastructure").definedBy("..com.test.infrastructure..")                .whereLayer("Controllers").mayNotBeAccessedByAnyLayer()                .whereLayer("Services").mayOnlyBeAccessedByLayers("Controllers")                .whereLayer("Infrastructure").mayOnlyBeAccessedByLayers("Services");        myRule.check(importedClasses);    }}

We make a violation of the above rules to see that our test fails — we inject a service into the repository.

我们违反了以上规则,看到我们的测试失败了—我们将服务注入到存储库中。

package com.test.infrastructure;import com.test.services.SecondService;public class FirstRepository {    SecondService secondService;    public FirstRepository(SecondService secondService) {        this.secondService = secondService;    }}

When we run the test we will see that our repository violates the rules:

运行测试时,我们将看到我们的存储库违反了规则:

结语 (Wrapping up)

ArchUnit, as you see, ensures that your project has the right architecture. It helps you to keep the project structure clean and prevents developers from making breaking changes.

如您所见,ArchUnit确保您的项目具有正确的体系结构。 它可以帮助您保持项目结构的清洁,并防止开发人员进行重大更改。

We have done a brief overview of the library. Besides all of its features, I think it would be great if ArchUnit would have some rules to test hexagonal architecture, cqrs and some DDD concepts like aggregates, value objects, etc.

我们已经对该库进行了简要概述。 除了所有功能之外,我认为ArchUnit拥有一些规则来测试六角形体系结构 , cqrs和一些DDD概念(如聚合,值对象等)将是很棒的。

For curious ones, here is the code on Github:

对于好奇的人,这里是Github上的代码:

mstrYoda/java-archunit-examplesContribute to mstrYoda/java-archunit-examples development by creating an account on GitHub.github.comTNG/ArchUnitA Java architecture test library, to specify and assert architecture rules in plain Java - TNG/ArchUnitgithub.comUnit test your Java architectureStart enforcing your architecture within 30 minutes using the test setup you already have.www.archunit.org

mstrYoda / java-archunit-examples 通过在GitHub上创建一个帐户为mstrYoda / java-archunit-examples开发做出贡献。 github.com TNG / ArchUnit 一个Java架构测试库,用于以纯Java指定和声明架构规则 -TNG / ArchUnit github.com 对Java架构进行单元测试 开始使用已有的测试设置在30分钟内开始实施架构。 www.archunit.org

翻译自: https://www.freecodecamp.org/news/java-archunit-testing-the-architecture-a09f089585be/

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

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

相关文章

解决ionic3 android 运行出现Application Error - The connection to the server was unsuccessful

在真机上启动ionic3打包成的android APK,启动了很久结果弹出这个问题: Application Error - The connection to the server was unsuccessful 可能是我项目资源太多东西了,启动的时间太久了,导致超时了。 解决方案是在项目目录下的config.xml…

特征工程之特征选择_特征工程与特征选择

特征工程之特征选择📈Python金融系列 (📈Python for finance series) Warning: There is no magical formula or Holy Grail here, though a new world might open the door for you.警告 : 这里没有神奇的配方或圣杯,尽管新世界可…

搭建Harbor企业级docker仓库

https://www.cnblogs.com/pangguoping/p/7650014.html 转载于:https://www.cnblogs.com/gcgc/p/11377461.html

leetcode 131. 分割回文串(dp+回溯)

给你一个字符串 s,请你将 s 分割成一些子串,使每个子串都是 回文串 。返回 s 所有可能的分割方案。 回文串 是正着读和反着读都一样的字符串。 示例 1: 输入:s “aab” 输出:[[“a”,“a”,“b”],[“aa”,“b”]]…

[翻译练习] 对视图控制器压入导航栈进行测试

译自:swiftandpainless.com/testing-pus… 上个月我写的关于使用 Swift 进行测试驱动开发的书终于出版了,我会在本文和接下来的一些博文中介绍这本书撰写过程中的一些心得和体会。 在本文中,我将会展示一种很好的用来测试一个视图控制器是否因…

python多人游戏服务器_Python在线多人游戏开发教程

python多人游戏服务器This Python online game tutorial from Tech with Tim will show you how to code a scaleable multiplayer game with python using sockets/networking and pygame. You will learn how to deploy your game so that people anywhere around the world …

版本号控制-GitHub

前面几篇文章。我们介绍了Git的基本使用方法及Gitserver的搭建。本篇文章来学习一下怎样使用GitHub。GitHub是开源的代码库以及版本号控制库,是眼下使用网络上使用最为广泛的服务,GitHub能够托管各种Git库。首先我们须要注冊一个GitHub账号,打…

leetcode132. 分割回文串 II(dp)

给你一个字符串 s,请你将 s 分割成一些子串,使每个子串都是回文。 返回符合要求的 最少分割次数 。 示例 1: 输入:s “aab” 输出:1 解释:只需一次分割就可将 s 分割成 [“aa”,“b”] 这样两个回文子串…

数据标准化和离散化

在某些比较和评价的指标处理中经常需要去除数据的单位限制,将其转化为无量纲的纯数值,便于不同单位或量级的指标能够进行比较和加权。因此需要通过一定的方法进行数据标准化,将数据按比例缩放,使之落入一个小的特定区间。 一、标准…

熊猫tv新功能介绍_熊猫简单介绍

熊猫tv新功能介绍Out of all technologies that is introduced in Data Analysis, Pandas is one of the most popular and widely used library.在Data Analysis引入的所有技术中,P andas是最受欢迎和使用最广泛的库之一。 So what are we going to cover :那么我…

关于sublime-text-2的Package Control组件安装方法,自动和手动

之前在自己的文章《Linux下安装以及破解sublim-text-2编辑器》的文章中提到过关于sublime-text-2的Package Control组件安装方法。 当时使用的是粘贴代码: 1import urllib2,os;pfPackage Control.sublime-package;ippsublime.installed_packages_path();os.makedirs…

上海区块链会议演讲ppt_进行第一次会议演讲的完整指南

上海区块链会议演讲pptConferences can be stressful even if you are not giving a talk. On the other hand, speaking can really boost your career, help you network, allow you to travel for (almost) free, and give back to others at the same time.即使您不讲话…

windows下Call to undefined function curl_init() error问题

本地项目中使用到curl_init()时出现Call to undefined function curl_init()的错误,去掉php.ini中的extensionphp_curl.dll前的分号还是不行,phpinfo()中无curl模块,于是上网搜索并实践了如下方法,成功: 在使用php5的c…

数据转换软件_数据转换

数据转换软件📈Python金融系列 (📈Python for finance series) Warning: There is no magical formula or Holy Grail here, though a new world might open the door for you.警告 :这里没有神奇的配方或圣杯,尽管新世界可能为您…

leetcode 1047. 删除字符串中的所有相邻重复项(栈)

给出由小写字母组成的字符串 S,重复项删除操作会选择两个相邻且相同的字母,并删除它们。 在 S 上反复执行重复项删除操作,直到无法继续删除。 在完成所有重复项删除操作后返回最终的字符串。答案保证唯一。 示例: 输入&#x…

spring boot: spring Aware的目的是为了让Bean获得Spring容器的服务

Spring Aware的目的是为了让Bean获得Spring容器的服务 //获取容器中的bean名称import org.springframework.beans.factory.BeanNameAware;//获得资源加载器,可以获得额外的资源import org.springframework.context.ResourceLoaderAware; package ch2.aware; import …

10张图带你深入理解Docker容器和镜像

【编者的话】本文用图文并茂的方式介绍了容器、镜像的区别和Docker每个命令后面的技术细节,能够很好的帮助读者深入理解Docker。这篇文章希望能够帮助读者深入理解Docker的命令,还有容器(container)和镜像(image&#…

matlab界area_Matlab的数据科学界

matlab界area意见 (Opinion) My personal interest in Data Science spans back to 2011. I was learning more about Economies and wanted to experiment with some of the ‘classic’ theories and whilst many of them held ground, at a micro level, many were also pur…

javascript异步_JavaScript异步并在循环中等待

javascript异步Basic async and await is simple. Things get a bit more complicated when you try to use await in loops.基本的async和await很简单。 当您尝试在循环中使用await时,事情会变得更加复杂。 In this article, I want to share some gotchas to wat…

白盒测试目录导航

白盒测试目录导航(更新中) 2017-12-29 [1] 白盒测试:为什么要做白盒测试 [2] 白盒测试:理论基础 [3] 白盒测试实战(上) [4] 白盒测试实战(中) [5] 白盒测试实战(下&#…