1

Merge pull request #56 from hhu-propra2/ArchitectureTests

Architecture tests with ArchUnit
This commit is contained in:
Christoph
2020-03-10 16:50:37 +01:00
committed by GitHub
7 changed files with 223 additions and 91 deletions

View File

@ -2,6 +2,8 @@ package mops.gruppen2.repository;
import mops.gruppen2.domain.EventDTO;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface EventRepository extends CrudRepository<EventDTO, Long> {
}

View File

@ -1,91 +0,0 @@
package mops.gruppen2.architecture;
import com.tngtech.archunit.junit.AnalyzeClasses;
import com.tngtech.archunit.junit.ArchIgnore;
import com.tngtech.archunit.junit.ArchTest;
import com.tngtech.archunit.lang.ArchRule;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.classes;
import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.noClasses;
@AnalyzeClasses(packages = "mops.gruppen2")
public class ArchUnitTest {
@ArchTest
public static final ArchRule controllerClassesShouldBeAnnotatedWithControllerOrRestControllerAnnotation = classes()
.that().haveSimpleNameEndingWith("Controller")
.should().beAnnotatedWith(Controller.class)
.orShould().beAnnotatedWith(RestController.class);
@ArchTest
public static final ArchRule controllerClassesShouldHaveControllerInName = classes()
.that().areAnnotatedWith(Controller.class)
.or().areAnnotatedWith(RestController.class)
.should().haveSimpleNameEndingWith("Controller");
@ArchTest
public static final ArchRule controllerClassesShouldBeInControllerPackage = classes()
.that().areAnnotatedWith(Controller.class)
.or().areAnnotatedWith(RestController.class)
.should().resideInAPackage("..controller..");
@ArchTest
public static final ArchRule noClassesWithControllerOrRestControllerAnnotationShouldResideOutsideOfControllerPackage = noClasses()
.that().areAnnotatedWith(Controller.class)
.or().areAnnotatedWith(RestController.class)
.should().resideOutsideOfPackage("..controller..");
@ArchTest
public static final ArchRule controllerClassesShouldHaveRequestMappingAnnotation = classes()
.that().resideInAPackage("..controller..")
.and().haveSimpleNameEndingWith("Controller")
.and().areAnnotatedWith(Controller.class)
.or().areAnnotatedWith(RestController.class)
.should().beAnnotatedWith(RequestMapping.class);
@ArchTest
public static final ArchRule controllerClassesShouldNotDependOnEachOther = noClasses()
.that().haveSimpleNameEndingWith("Controller")
.should().dependOnClassesThat().haveNameMatching("Controller");
@ArchTest
public static final ArchRule serviceClassesShouldHaveServiceInName = classes()
.that().areAnnotatedWith(Service.class)
.should().haveSimpleNameEndingWith("Service");
@ArchTest
public static final ArchRule serviceClassesShouldBeAnnotatedWithService = classes()
.that().haveSimpleNameEndingWith("Service")
.should().beAnnotatedWith(Service.class);
@ArchTest
public static final ArchRule serviceClassesShouldBeInServicePackage = classes()
.that().areAnnotatedWith(Service.class)
.should().resideInAPackage("..service..");
@ArchTest
public static final ArchRule serviceClassesShouldOnlyBeAccessedByControllerOrServiceClasses = classes()
.that().resideInAPackage("..service..")
.should().onlyBeAccessed().byAnyPackage("..controller..", "..service..");
@ArchTest
public static final ArchRule domainClassesShouldNotAccessOtherClasses = noClasses()
.that().resideInAPackage("..domain..")
.should().accessClassesThat().resideInAnyPackage("..controller..", "..repository..", "..security..", "..service..");
@ArchTest
public static final ArchRule repositoryClassesThatImplementCrudRepositoryShouldBeNamedRepository = classes()
.that().implement(CrudRepository.class)
.should().haveSimpleNameEndingWith("Repository");
@ArchTest
public static final ArchRule repositoryClassesShouldBeInRepositoryPackage = classes()
.that().haveSimpleNameEndingWith("Repository")
.should().resideInAPackage("..repository..");
}

View File

@ -0,0 +1,53 @@
package mops.gruppen2.architecture;
import com.tngtech.archunit.core.importer.ImportOption;
import com.tngtech.archunit.junit.AnalyzeClasses;
import com.tngtech.archunit.junit.ArchTest;
import com.tngtech.archunit.lang.ArchRule;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.classes;
import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.noClasses;
@AnalyzeClasses(packages = "mops.gruppen2", importOptions = { ImportOption.DoNotIncludeTests.class })
public class ControllerTest {
@ArchTest
public static final ArchRule controllerClassesShouldBeAnnotatedWithControllerOrRestControllerAnnotation = classes()
.that().haveSimpleNameEndingWith("Controller")
.should().beAnnotatedWith(Controller.class)
.orShould().beAnnotatedWith(RestController.class);
@ArchTest
public static final ArchRule controllerClassesShouldHaveControllerInName = classes()
.that().areAnnotatedWith(Controller.class)
.or().areAnnotatedWith(RestController.class)
.should().haveSimpleNameEndingWith("Controller");
@ArchTest
public static final ArchRule controllerClassesShouldBeInControllerPackage = classes()
.that().areAnnotatedWith(Controller.class)
.or().areAnnotatedWith(RestController.class)
.should().resideInAPackage("..controller..");
@ArchTest
public static final ArchRule classesInControllerPackageShouldHaveControllerInName = classes()
.that().resideInAPackage("..controller..")
.should().haveSimpleNameEndingWith("Controller");
@ArchTest
public static final ArchRule controllerClassesShouldHaveRequestMappingAnnotation = classes()
.that().resideInAPackage("..controller..")
.and().haveSimpleNameEndingWith("Controller")
.and().areAnnotatedWith(Controller.class)
.or().areAnnotatedWith(RestController.class)
.should().beAnnotatedWith(RequestMapping.class);
@ArchTest
public static final ArchRule controllerClassesShouldNotDependOnEachOther = noClasses()
.that().haveSimpleNameEndingWith("Controller")
.should().dependOnClassesThat().haveNameMatching("Controller");
}

View File

@ -0,0 +1,50 @@
package mops.gruppen2.architecture;
import com.tngtech.archunit.core.importer.ImportOption;
import com.tngtech.archunit.junit.AnalyzeClasses;
import com.tngtech.archunit.junit.ArchIgnore;
import com.tngtech.archunit.junit.ArchTest;
import com.tngtech.archunit.lang.ArchRule;
import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.classes;
import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.noClasses;
@AnalyzeClasses(packages = "mops.gruppen2", importOptions = { ImportOption.DoNotIncludeTests.class })
public class DomainTest {
@ArchTest
public static final ArchRule domainClassesShouldNotAccessClassesFromOtherPackagesExceptDomainItself = noClasses()
.that().resideInAPackage("..domain..")
.should().accessClassesThat().resideInAnyPackage("..controller..", "..repository..", "..security..", "..service..");
@ArchTest
public static final ArchRule eventClassesShouldBeInEventPackage = classes()
.that().haveSimpleNameEndingWith("Event")
.should().resideInAPackage("..domain.event..");
@ArchTest
public static final ArchRule classesInEventPackageShouldHaveEventInName = classes()
.that().resideInAPackage("..domain.event..")
.should().haveSimpleNameEndingWith("Event");
@ArchTest
public static final ArchRule exceptionClassesShouldBeInExceptionPackage = classes()
.that().haveSimpleNameEndingWith("Exception")
.should().resideInAPackage("..domain.Exceptions..");
@ArchTest
public static final ArchRule classesInExceptionPackageShouldHaveExceptionInName = classes()
.that().resideInAPackage("..domain.Exceptions..")
.should().haveSimpleNameEndingWith("Exception");
@ArchTest
public static final ArchRule classesThatAreAssignableToExceptionShouldHaveExceptionInName = classes()
.that().areAssignableTo(Exception.class)
.should().haveSimpleNameEndingWith("Exception");
@ArchTest
public static final ArchRule classesThatHaveExceptionInNameShouldBeAssignableToExceptionClass = classes()
.that().haveSimpleNameEndingWith("Exception")
.should().beAssignableTo(Exception.class);
}

View File

@ -0,0 +1,39 @@
package mops.gruppen2.architecture;
import com.tngtech.archunit.core.importer.ImportOption;
import com.tngtech.archunit.junit.AnalyzeClasses;
import com.tngtech.archunit.junit.ArchTest;
import com.tngtech.archunit.lang.ArchRule;
import com.tngtech.archunit.library.Architectures;
@AnalyzeClasses(packages = "mops.gruppen2", importOptions = { ImportOption.DoNotIncludeTests.class })
public class LayeredArchitectureTest {
private static Architectures.LayeredArchitecture layeredArchitecture = Architectures
.layeredArchitecture()
.layer("Domain").definedBy("..domain..")
.layer("Service").definedBy("..service")
.layer("Controller").definedBy("..controller..")
.layer("Repository").definedBy("..repository..");
@ArchTest
public static final ArchRule domainLayerShouldOnlyBeAccessedByServiceAndControllerLayer = layeredArchitecture
.whereLayer("Domain")
.mayOnlyBeAccessedByLayers("Service", "Controller");
@ArchTest
public static final ArchRule serviceLayerShouldOnlyBeAccessedByControllerLayer = layeredArchitecture
.whereLayer("Service")
.mayOnlyBeAccessedByLayers("Controller");
@ArchTest
public static final ArchRule repositoryLayerShouldOnlyBeAccessedByServiceLayer = layeredArchitecture
.whereLayer("Repository")
.mayOnlyBeAccessedByLayers("Service");
@ArchTest
public static final ArchRule controllerLayerShouldNotBeAccessedByAnyLayer = layeredArchitecture
.whereLayer("Controller")
.mayNotBeAccessedByAnyLayer();
}

View File

@ -0,0 +1,40 @@
package mops.gruppen2.architecture;
import com.tngtech.archunit.core.importer.ImportOption;
import com.tngtech.archunit.junit.AnalyzeClasses;
import com.tngtech.archunit.junit.ArchTest;
import com.tngtech.archunit.lang.ArchRule;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;
import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.classes;
@AnalyzeClasses(packages = "mops.gruppen2", importOptions = { ImportOption.DoNotIncludeTests.class })
public class RepositoryTest {
@ArchTest
public static final ArchRule repositoryClassesThatAreAnnotatedWithRepositoryShouldHaveRepositoryInName = classes()
.that().areAnnotatedWith(Repository.class)
.should().haveSimpleNameEndingWith("Repository");
@ArchTest
public static final ArchRule repositoryClassesShouldBeInRepositoryPackage = classes()
.that().haveSimpleNameEndingWith("Repository")
.should().resideInAPackage("..repository..");
@ArchTest
public static final ArchRule repositoryClassesShouldBeAnnotatedWithRepositoryAnnotation = classes()
.that().haveSimpleNameEndingWith("Repository")
.should().beAnnotatedWith(Repository.class);
@ArchTest
public static final ArchRule classesInRepositoryPackageShouldHaveRepositoryInName = classes()
.that().resideInAPackage("..repository..")
.should().haveSimpleNameEndingWith("Repository");
@ArchTest
public static final ArchRule classesThatAreAssignableToCrudRepositoryShouldHaveRepositoryInName = classes()
.that().areAssignableTo(CrudRepository.class)
.should().beAnnotatedWith(Repository.class);
}

View File

@ -0,0 +1,39 @@
package mops.gruppen2.architecture;
import com.tngtech.archunit.core.importer.ImportOption;
import com.tngtech.archunit.junit.AnalyzeClasses;
import com.tngtech.archunit.junit.ArchTest;
import com.tngtech.archunit.lang.ArchRule;
import org.springframework.stereotype.Service;
import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.classes;
@AnalyzeClasses(packages = "mops.gruppen2", importOptions = { ImportOption.DoNotIncludeTests.class })
public class ServiceTest {
@ArchTest
public static final ArchRule serviceClassesShouldHaveServiceInName = classes()
.that().areAnnotatedWith(Service.class)
.should().haveSimpleNameEndingWith("Service");
@ArchTest
public static final ArchRule serviceClassesShouldBeAnnotatedWithService = classes()
.that().haveSimpleNameEndingWith("Service")
.should().beAnnotatedWith(Service.class);
@ArchTest
public static final ArchRule serviceClassesShouldBeInServicePackage = classes()
.that().areAnnotatedWith(Service.class)
.should().resideInAPackage("..service..");
@ArchTest
public static final ArchRule classesInServicePackageShouldHaveServiceInName = classes()
.that().resideInAPackage("..service..")
.should().haveSimpleNameEndingWith("Service");
@ArchTest
public static final ArchRule serviceClassesShouldOnlyBeAccessedByControllerOrServiceClasses = classes()
.that().resideInAPackage("..service..")
.should().onlyBeAccessed().byAnyPackage("..controller..", "..service..");
}