Merge pull request #9785 from psevestre/master

[BAEL-4381] Introduction to ArchUnit
This commit is contained in:
bfontana 2020-08-18 12:47:15 -03:00 committed by GitHub
commit 51558e1d47
7 changed files with 267 additions and 3 deletions

View File

@ -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>

View File

@ -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));
}
}

View File

@ -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;
}
}

View File

@ -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();
}
}

View File

@ -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());
}
}

View File

@ -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;
}
}

View File

@ -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);
}
}