演示:React + Spring + ArchUnit的開源專案

banq發表於2022-05-14

使用 ArchUnit 強化Java架構:展示如何使用 Spring 執行前端 (React) 和後端 (Java) 的 Java開源專案,建立具有前端和後端的專案,以便在本地或透過瀏覽器輕鬆執行。

前端技術:
  • JavaScript
  • React 17.0.2
  • MUI 5
  • Jest
  • GitHub actions


後端Java:
  • Java 11
  • SpringBoot 2.6.3
  • Spring
  • Hibernate
  • Swagger - OpenAPI 1.6.7
  • MapStruct
  • GitHub actions
  • Gradle — 7.4
  • ArchUnit — 0.23.1
  • JUnit 5–5.8.2


這是一個單體分層架構
  • 1st → 專案層
  • 2nd → 單元測試,我們對更好架構的守護者
  • 3rd → Gradle 構建檔案
  • 4th → 對archUnit的依賴


UT(單元測試)
只需一個 UT,您就可以設定您的監護人來保證系統架構。
在我們的設定中,首先我們需要通知 UT 不考慮測試包。如果您的情況有任何例外,請也新增到設定中。
然後是一個愚蠢的測試,說任何 web 包都可以被 web 包內的任何類訪問。
最後,更重要的是關於層,我們控制層,非常出色:

package com.costa.luiz.zero2hero;

import com.tngtech.archunit.core.domain.JavaClasses;
import com.tngtech.archunit.core.importer.ClassFileImporter;
import com.tngtech.archunit.core.importer.ImportOption;
import com.tngtech.archunit.lang.ArchRule;
import com.tngtech.archunit.library.Architectures;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;

import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.classes;
import static com.tngtech.archunit.library.Architectures.layeredArchitecture;

class ArchitectureGuardianTest {

    private static JavaClasses importedClasses;

    @BeforeAll
    static void setUp() {
        ImportOption ignoreTests = location -> {
            return !location.contains("/test/"); // ignore any URI to sources that contains '/test/'
        };
        importedClasses = new ClassFileImporter().withImportOption(ignoreTests).importPackages("com.costa.luiz.zero2hero");
    }

    @Test
    void webShouldOnlyBeAccessedByWeb() {
        ArchRule serviceRule = classes()
                .that().resideInAPackage("..web..")
                .should().onlyBeAccessed()
                .byAnyPackage("..web..");
        serviceRule.check(importedClasses);
    }

    @Test
    void layeredArchitectureGuardian() {
        Architectures.LayeredArchitecture layeredArchitecture = layeredArchitecture()
                .layer("Controller").definedBy("..web..")
                .layer("Business").definedBy("..business..")
                .layer("Persistence").definedBy("..persistence..")
                .whereLayer("Controller").mayNotBeAccessedByAnyLayer()
                .whereLayer("Business").mayOnlyBeAccessedByLayers("Controller", "Business")
                .whereLayer("Persistence").mayOnlyBeAccessedByLayers("Business");

        layeredArchitecture.check(importedClasses);
    }
}


 

相關文章