Merge pull request #9785 from psevestre/master
[BAEL-4381] Introduction to ArchUnit
This commit is contained in:
commit
51558e1d47
|
@ -1,7 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>libraries-testing</artifactId>
|
||||
<name>libraries-testing</name>
|
||||
|
@ -158,6 +158,13 @@
|
|||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.tngtech.archunit</groupId>
|
||||
<artifactId>archunit-junit5</artifactId>
|
||||
<version>${archunit.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
@ -193,7 +200,7 @@
|
|||
|
||||
<properties>
|
||||
<asciidoctor.version>1.5.7.1</asciidoctor.version>
|
||||
<serenity.version>1.9.9</serenity.version>
|
||||
<serenity.version>1.9.9</serenity.version>
|
||||
<serenity.jbehave.version>1.9.0</serenity.jbehave.version>
|
||||
<serenity.jira.version>1.9.0</serenity.jira.version>
|
||||
<serenity.plugin.version>1.9.27</serenity.plugin.version>
|
||||
|
@ -210,6 +217,7 @@
|
|||
<maven-compiler-plugin.target>1.8</maven-compiler-plugin.target>
|
||||
<maven-compiler-plugin.source>1.8</maven-compiler-plugin.source>
|
||||
<maven-compiler-plugin.version>3.8.1</maven-compiler-plugin.version>
|
||||
<archunit.version>0.14.1</archunit.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
package com.baeldung.archunit.smurfs.persistence;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import com.baeldung.archunit.smurfs.persistence.domain.Smurf;
|
||||
|
||||
import static java.util.stream.Collectors.toList;
|
||||
|
||||
public class SmurfsRepository {
|
||||
|
||||
private static Map<String,Smurf> smurfs = Collections.synchronizedMap(new TreeMap<>());
|
||||
|
||||
static {
|
||||
// Just a few here. A full list can be found
|
||||
// at https://smurfs.fandom.com/wiki/List_of_Smurf_characters
|
||||
smurfs.put("Papa", new Smurf("Papa", true, true));
|
||||
smurfs.put("Actor", new Smurf("Actor", true, true));
|
||||
smurfs.put("Alchemist", new Smurf("Alchemist", true, true));
|
||||
smurfs.put("Archeologist", new Smurf("Archeologist", true, true));
|
||||
smurfs.put("Architect", new Smurf("Architect", true, true));
|
||||
smurfs.put("Baby", new Smurf("Baby", true, true));
|
||||
smurfs.put("Baker", new Smurf("Baker", true, true));
|
||||
smurfs.put("Baker", new Smurf("Baker", true, true));
|
||||
}
|
||||
|
||||
public List<Smurf> findAll() {
|
||||
return Collections.unmodifiableList(smurfs.values().stream().collect(toList()));
|
||||
}
|
||||
|
||||
public Optional<Smurf> findByName(String name) {
|
||||
return Optional.of(smurfs.get(name));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
package com.baeldung.archunit.smurfs.persistence.domain;
|
||||
|
||||
public class Smurf {
|
||||
private String name;
|
||||
private boolean comic;
|
||||
private boolean cartoon;
|
||||
|
||||
public Smurf() {}
|
||||
|
||||
public Smurf(String name, boolean comic, boolean cartoon) {
|
||||
this.name = name;
|
||||
this.comic = comic;
|
||||
this.cartoon = cartoon;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public boolean isComic() {
|
||||
return comic;
|
||||
}
|
||||
|
||||
public void setCommic(boolean comic) {
|
||||
this.comic = comic;
|
||||
}
|
||||
|
||||
public boolean isCartoon() {
|
||||
return cartoon;
|
||||
}
|
||||
|
||||
public void setCartoon(boolean cartoon) {
|
||||
this.cartoon = cartoon;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
package com.baeldung.archunit.smurfs.presentation;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import com.baeldung.archunit.smurfs.service.SmurfsService;
|
||||
import com.baeldung.archunit.smurfs.service.dto.SmurfDTO;
|
||||
|
||||
@RequestMapping(value = "/smurfs", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
|
||||
@RestController
|
||||
public class SmurfsController {
|
||||
|
||||
private SmurfsService smurfs;
|
||||
|
||||
public SmurfsController(SmurfsService smurfs) {
|
||||
this.smurfs = smurfs;
|
||||
}
|
||||
|
||||
@GetMapping
|
||||
public List<SmurfDTO> getSmurfs() {
|
||||
return smurfs.findAll();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
|
||||
package com.baeldung.archunit.smurfs.service;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import com.baeldung.archunit.smurfs.persistence.SmurfsRepository;
|
||||
import com.baeldung.archunit.smurfs.persistence.domain.Smurf;
|
||||
import com.baeldung.archunit.smurfs.service.dto.SmurfDTO;
|
||||
|
||||
@Component
|
||||
public class SmurfsService {
|
||||
|
||||
private SmurfsRepository repository;
|
||||
|
||||
public SmurfsService(SmurfsRepository repository) {
|
||||
this.repository = repository;
|
||||
}
|
||||
|
||||
public List<SmurfDTO> findAll() {
|
||||
|
||||
return repository.findAll()
|
||||
.stream()
|
||||
.map(SmurfsService::toDTO)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
|
||||
public static SmurfDTO toDTO(Smurf smurf) {
|
||||
return new SmurfDTO(smurf.getName(),smurf.isComic(), smurf.isCartoon());
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
|
||||
package com.baeldung.archunit.smurfs.service.dto;
|
||||
|
||||
public class SmurfDTO {
|
||||
private String name;
|
||||
private boolean comic;
|
||||
private boolean cartoon;
|
||||
|
||||
public SmurfDTO() {}
|
||||
|
||||
public SmurfDTO(String name, boolean comic, boolean cartoon) {
|
||||
this.name = name;
|
||||
this.comic = comic;
|
||||
this.cartoon = cartoon;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public boolean isComic() {
|
||||
return comic;
|
||||
}
|
||||
|
||||
public void setCommic(boolean comic) {
|
||||
this.comic = comic;
|
||||
}
|
||||
|
||||
public boolean isCartoon() {
|
||||
return cartoon;
|
||||
}
|
||||
|
||||
public void setCartoon(boolean cartoon) {
|
||||
this.cartoon = cartoon;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
package com.baeldung.archunit.smurfs;
|
||||
|
||||
|
||||
import com.tngtech.archunit.core.domain.JavaClasses;
|
||||
import com.tngtech.archunit.core.importer.ClassFileImporter;
|
||||
import com.tngtech.archunit.lang.ArchRule;
|
||||
import com.tngtech.archunit.library.Architectures.LayeredArchitecture;
|
||||
|
||||
import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.classes;
|
||||
import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.noClasses;
|
||||
import static com.tngtech.archunit.library.Architectures.layeredArchitecture;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
public class SmurfsArchUnitTest {
|
||||
|
||||
@Test
|
||||
public void givenPresentationLayerClasses_thenWrongCheckFails() {
|
||||
JavaClasses jc = new ClassFileImporter().importPackages("com.baeldung.archunit.smurfs");
|
||||
|
||||
ArchRule r1 = classes()
|
||||
.that()
|
||||
.resideInAPackage("..presentation..")
|
||||
.should().onlyDependOnClassesThat()
|
||||
.resideInAPackage("..service..");
|
||||
|
||||
assertThrows(AssertionError.class, ()-> r1.check(jc)) ;
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void givenPresentationLayerClasses_thenCheckWithFrameworkDependenciesSuccess() {
|
||||
JavaClasses jc = new ClassFileImporter().importPackages("com.baeldung.archunit.smurfs");
|
||||
|
||||
ArchRule r1 = classes()
|
||||
.that()
|
||||
.resideInAPackage("..presentation..")
|
||||
.should().onlyDependOnClassesThat()
|
||||
.resideInAnyPackage("..service..", "java..", "javax..", "org.springframework..");
|
||||
|
||||
r1.check(jc);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenPresentationLayerClasses_thenNoPersistenceLayerAccess() {
|
||||
JavaClasses jc = new ClassFileImporter().importPackages("com.baeldung.archunit.smurfs");
|
||||
|
||||
ArchRule r1 = noClasses()
|
||||
.that()
|
||||
.resideInAPackage("..presentation..")
|
||||
.should().dependOnClassesThat()
|
||||
.resideInAPackage("..persistence..");
|
||||
|
||||
r1.check(jc);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenApplicationClasses_thenNoLayerViolationsShouldExist() {
|
||||
|
||||
JavaClasses jc = new ClassFileImporter().importPackages("com.baeldung.archunit.smurfs");
|
||||
|
||||
LayeredArchitecture arch = layeredArchitecture()
|
||||
// Define layers
|
||||
.layer("Presentation").definedBy("..presentation..")
|
||||
.layer("Service").definedBy("..service..")
|
||||
.layer("Persistence").definedBy("..persistence..")
|
||||
// Add constraints
|
||||
.whereLayer("Presentation").mayNotBeAccessedByAnyLayer()
|
||||
.whereLayer("Service").mayOnlyBeAccessedByLayers("Presentation")
|
||||
.whereLayer("Persistence").mayOnlyBeAccessedByLayers("Service");
|
||||
|
||||
arch.check(jc);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue