При создании программного обеспечения группы разработчиков обычно определяют набор рекомендаций и соглашений по разработке кода, которые считаются лучшими практиками.
Это методы, которые обычно документируются и доводятся до сведения всей команды разработчиков, которая их приняла.
Однако во время разработки разработчики могут нарушать эти рекомендации, что обнаруживается во время проверки кода или при использовании инструментов контроля качества кода.
Поэтому важным аспектом является максимальная автоматизация этих директив по всей архитектуре проекта, позволяющая оптимизировать проверки.
Мы можем реализовать эти рекомендации в виде проверяемых тестов JUnit, используя АрхЮнит .
Это гарантирует, что сборка версии программного обеспечения будет остановлена, если архитектура нарушена.
АрхЮнит — это бесплатная, простая и расширяемая библиотека для тестирования архитектуры вашего кода Java для использования в любой простой среде модульного тестирования Java. То есть ArchUnit может проверять зависимости между пакетами и классами, уровнями и слайсами, проверять циклические зависимости и многое другое.ArchUnit позволяет реализовывать правила для статических свойств архитектуры приложения в виде исполняемых тестов, например следующие:Это делается путем анализа данного байт-кода Java и импорта всех классов в структуру кода Java.
- Проверка зависимостей пакетов
- Проверки зависимостей классов
- Проверка содержимого классов и пакетов
- Проверка наследства
- Проверка аннотаций
- Проверка уровней
- Циклические проверки
Примечание переводчика.Эта заметка дополняет предыдущий по теме ArchUnit.
Давайте начнем
Для поддержки ArchUnit JUnit 5 просто добавьте следующую зависимость из Maven Central:XMLpom.xml
<dependency>
<groupId>com.tngtech.archunit</groupId>
<artifactId>archunit-junit5</artifactId>
<version>0.14.1</version>
<scope>test</scope>
</dependency>
build.gradle
классный
dependencies {
testImplementation 'com.tngtech.archunit:archunit-junit5:0.14.1'
} }
Проверка зависимостей пакетов Джава
class ArchunitApplicationTests {
private JavaClasses importedClasses;
@BeforeEach
public void setup() {
importedClasses = new ClassFileImporter()
.
withImportOption(ImportOption.Predefined.DO_NOT_INCLUDE_TESTS)
.
importPackages("com.springboot.testing.archunit");
}
@Test
void servicesAndRepositoriesShouldNotDependOnWebLayer() {
noClasses()
.
that().
resideInAnyPackage("com.springboot.testing.archunit.service.")
.
or().
resideInAnyPackage("com.springboot.testing.archunit.repository.")
.
should()
.
dependOnClassesThat()
.
resideInAnyPackage("com.springboot.testing.archunit.controller.")
.
because("Services and repositories should not depend on web layer")
.
check(importedClasses);
}
}
Службы и репозитории не должны взаимодействовать с веб-уровнем.
Проверки зависимостей классов class ArchunitApplicationTests {
private JavaClasses importedClasses;
@BeforeEach
public void setup() {
importedClasses = new ClassFileImporter()
.
withImportOption(ImportOption.Predefined.DO_NOT_INCLUDE_TESTS) .
importPackages("com.springboot.testing.archunit"); } @Test void serviceClassesShouldOnlyBeAccessedByController() { classes() .
that().
resideInAPackage(".
service.") .
should().
onlyBeAccessed().
byAnyPackage(".
service.", ".
controller.") .
check(importedClasses);
}
}
ArchUnit предлагает абстрактный API-интерфейс, подобный DSL, который, помимо прочего, может оценивать импортированные классы.
Доступ к сервисам должен иметь только контроллер .
Две точки представляют любое количество пакетов (сравните AspectJ Pointcuts).
Соглашение об именовании Джава class ArchunitApplicationTests {
private JavaClasses importedClasses;
@BeforeEach
public void setup() {
importedClasses = new ClassFileImporter()
importedClasses = new ClassFileImporter()
.
withImportOption(ImportOption.Predefined.DO_NOT_INCLUDE_TESTS) .
importPackages("com.springboot.testing.archunit"); } @Test void serviceClassesShouldBeNamedXServiceOrXComponentOrXServiceImpl() { classes() .
that().
resideInAPackage(".
service.") .
should().
haveSimpleNameEndingWith("Service") .
orShould().
haveSimpleNameEndingWith("ServiceImpl") .
orShould().
haveSimpleNameEndingWith("Component") .
check(importedClasses); } @Test void repositoryClassesShouldBeNamedXRepository() { classes() .
that().
resideInAPackage(".
repository.") .
should().
haveSimpleNameEndingWith("Repository") .
check(importedClasses); } @Test void controllerClassesShouldBeNamedXController() { classes() .
that().
resideInAPackage(".
controller.") .
should().
haveSimpleNameEndingWith("Controller") .
check(importedClasses);
}
}
Общим правилом является соглашение об именах.
Например, имена всех классов обслуживания должны заканчиваться словами «Сервис», «Компонент» и т. д. Проверка аннотаций Джава class ArchunitApplicationTests {
private JavaClasses importedClasses;
@BeforeEach
public void setup() {
importedClasses = new ClassFileImporter()
.
withImportOption(ImportOption.Predefined.DO_NOT_INCLUDE_TESTS) .
importPackages("com.springboot.testing.archunit"); } @Test void fieldInjectionNotUseAutowiredAnnotation() { noFields() .
should().
beAnnotatedWith(Autowired.class) .
check(importedClasses); } @Test void repositoryClassesShouldHaveSpringRepositoryAnnotation() { classes() .
that().
resideInAPackage(".
repository.") .
should().
beAnnotatedWith(Repository.class) .
check(importedClasses); } @Test void serviceClassesShouldHaveSpringServiceAnnotation() { classes() .
that().
resideInAPackage(".
service.") .
should().
beAnnotatedWith(Service.class) .
check(importedClasses);
}
}
API ArchUnit Lang может определять правила для членов классов Java. Это может быть актуально, например, если методы в определенном контексте должны быть помечены определенной аннотацией или если возвращаемые типы реализуют определенный интерфейс.
Проверка уровня class ArchunitApplicationTests {
Теги: #java #тестирование #лучшие практики
-
Ответ Интернет-Хакерам
19 Oct, 24 -
Rxjava. Удаление Магии
19 Oct, 24 -
Радио-Э №8,5
19 Oct, 24 -
Задача Про Гномов И Разноцветные Шляпы
19 Oct, 24 -
Звездные Войны В Исходном Коде
19 Oct, 24