使用 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);
}
}
|