Skip to content

Commit c00f7eb

Browse files
schaudermp911de
authored andcommitted
Make dependency tests based on ArchUnit.
The DependencyTests are reimplemented using ArchUnit and enabled. This uncovered some dependency circles which got fixed: See #2708 Original pull request #2706
1 parent 6190baa commit c00f7eb

File tree

2 files changed

+110
-17
lines changed

2 files changed

+110
-17
lines changed

pom.xml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -335,9 +335,9 @@
335335
</dependency>
336336

337337
<dependency>
338-
<groupId>de.schauderhaft.degraph</groupId>
339-
<artifactId>degraph-check</artifactId>
340-
<version>0.1.4</version>
338+
<groupId>com.tngtech.archunit</groupId>
339+
<artifactId>archunit</artifactId>
340+
<version>${archunit}</version>
341341
<scope>test</scope>
342342
</dependency>
343343

src/test/java/org/springframework/data/DependencyTests.java

Lines changed: 107 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -15,29 +15,122 @@
1515
*/
1616
package org.springframework.data;
1717

18-
import static de.schauderhaft.degraph.check.JCheck.*;
19-
import static org.junit.Assert.*;
18+
import static org.assertj.core.api.Assertions.*;
2019

21-
import org.junit.jupiter.api.Disabled;
2220
import org.junit.jupiter.api.Test;
21+
import org.springframework.data.repository.core.RepositoryMetadata;
22+
23+
import com.tngtech.archunit.base.DescribedPredicate;
24+
import com.tngtech.archunit.core.domain.JavaClass;
25+
import com.tngtech.archunit.core.domain.JavaClasses;
26+
import com.tngtech.archunit.core.importer.ClassFileImporter;
27+
import com.tngtech.archunit.core.importer.ImportOption;
28+
import com.tngtech.archunit.lang.ArchRule;
29+
import com.tngtech.archunit.library.dependencies.SlicesRuleDefinition;
2330

2431
/**
32+
* Tests for package and slice cycles. All packages that have the same start including the part after {@literal data}
33+
* are considered one slice. For example {@literal org.springframework.data.repository} and
34+
* {@literal org.springframework.data.repository.support} are part of the same slice {@literal repository}.
35+
*
2536
* @author Jens Schauder
2637
*/
27-
@Disabled("Requires newer version of ASM 5.1")
2838
public class DependencyTests {
2939

40+
JavaClasses importedClasses = new ClassFileImporter() //
41+
.withImportOption(ImportOption.Predefined.DO_NOT_INCLUDE_TESTS) //
42+
.withImportOption(ImportOption.Predefined.DO_NOT_INCLUDE_JARS) // we just analyze the code of this module.
43+
.importPackages("org.springframework.data") //
44+
.that(onlySpringData()) //
45+
46+
// new cycle
47+
.that(ignore(RepositoryMetadata.class));
48+
49+
@Test
50+
void cycleFreeSlices() {
51+
52+
ArchRule rule = SlicesRuleDefinition.slices() //
53+
.matching("org.springframework.data.(*)..") //
54+
.should() //
55+
.beFreeOfCycles();
56+
57+
rule.check(importedClasses);
58+
}
59+
60+
@Test
61+
void cycleFreePackages() {
62+
63+
ArchRule rule = SlicesRuleDefinition.slices() //
64+
.matching("org.springframework.data.(**)") //
65+
.should() //
66+
.beFreeOfCycles();
67+
68+
rule.check(importedClasses);
69+
}
70+
71+
@Test
72+
void testGetFirstPackagePart() {
73+
74+
assertThat(getFirstPackagePart("a.b.c")).isEqualTo("a");
75+
assertThat(getFirstPackagePart("a")).isEqualTo("a");
76+
}
77+
3078
@Test
31-
public void noInternalPackageCycles() {
32-
33-
assertThat(
34-
classpath() //
35-
.noJars() //
36-
.including("org.springframework.data.**") //
37-
.filterClasspath("*target/classes") //
38-
.printOnFailure("degraph.graphml"), //
39-
violationFree() //
40-
);
79+
void testSubModule() {
80+
81+
assertThat(subModule("a.b", "a.b.c.d")).isEqualTo("c");
82+
assertThat(subModule("a.b", "a.b.c")).isEqualTo("c");
83+
assertThat(subModule("a.b", "a.b")).isEqualTo("");
84+
}
85+
86+
private DescribedPredicate<JavaClass> onlySpringData() {
87+
88+
return new DescribedPredicate<>("Spring Data Classes") {
89+
@Override
90+
public boolean test(JavaClass input) {
91+
return input.getPackageName().startsWith("org.springframework.data");
92+
}
93+
};
94+
}
95+
96+
private DescribedPredicate<JavaClass> ignore(Class<?> type) {
97+
98+
return new DescribedPredicate<>("ignored class " + type.getName()) {
99+
@Override
100+
public boolean test(JavaClass input) {
101+
return !input.getFullName().startsWith(type.getName());
102+
}
103+
};
104+
}
105+
106+
private DescribedPredicate<JavaClass> ignorePackage(String type) {
107+
108+
return new DescribedPredicate<>("ignored class " + type) {
109+
@Override
110+
public boolean test(JavaClass input) {
111+
return !input.getPackageName().equals(type);
112+
}
113+
};
114+
}
115+
116+
private String getFirstPackagePart(String subpackage) {
117+
118+
int index = subpackage.indexOf(".");
119+
if (index < 0) {
120+
return subpackage;
121+
}
122+
return subpackage.substring(0, index);
123+
}
124+
125+
private String subModule(String basePackage, String packageName) {
126+
127+
if (packageName.startsWith(basePackage) && packageName.length() > basePackage.length()) {
128+
129+
final int index = basePackage.length() + 1;
130+
String subpackage = packageName.substring(index);
131+
return getFirstPackagePart(subpackage);
132+
}
133+
return "";
41134
}
42135

43136
}

0 commit comments

Comments
 (0)