如何使用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.pswp.cn/news/391657.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/391657.shtml
英文地址,請注明出處:http://en.pswp.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] 白盒測試實戰(下&#…