47 lines
3.6 KiB
Plaintext
47 lines
3.6 KiB
Plaintext
Captured from a real `mvn test` run with a temporary class added to the controller
|
|
package, com.ankurm.tutorials.junit.archunit.controller.BadOrderLookupController,
|
|
whose constructor took OrderRepository directly instead of going through
|
|
OrderStatusService. The class was deleted immediately after this run; it exists
|
|
only in this transcript and in the "before/after" diagram in the published post.
|
|
|
|
[INFO] Running com.ankurm.tutorials.junit.archunit.LayeredArchitectureTest
|
|
[ERROR] Tests run: 3, Failures: 1, Errors: 0, Skipped: 0, Time elapsed: 1.445 s <<< FAILURE! -- in com.ankurm.tutorials.junit.archunit.LayeredArchitectureTest
|
|
[ERROR] LayeredArchitectureTest.controllersOnlyCallServicesWhichOnlyCallRepositories -- Time elapsed: 1.402 s <<< FAILURE!
|
|
java.lang.AssertionError:
|
|
Architecture Violation [Priority: MEDIUM] - Rule 'Layered architecture considering all dependencies, consisting of
|
|
layer 'Controller' ('..controller..')
|
|
layer 'Service' ('..service..')
|
|
layer 'Repository' ('..repository..')
|
|
where layer 'Controller' may not be accessed by any layer
|
|
where layer 'Service' may only be accessed by layers ['Controller']
|
|
where layer 'Repository' may only be accessed by layers ['Service']' was violated (3 times):
|
|
Constructor <com.ankurm.tutorials.junit.archunit.controller.BadOrderLookupController.<init>(com.ankurm.tutorials.junit.archunit.repository.OrderRepository)> has parameter of type <com.ankurm.tutorials.junit.archunit.repository.OrderRepository> in (BadOrderLookupController.java:0)
|
|
Field <com.ankurm.tutorials.junit.archunit.controller.BadOrderLookupController.orderRepository> has type <com.ankurm.tutorials.junit.archunit.repository.OrderRepository> in (BadOrderLookupController.java:0)
|
|
Method <com.ankurm.tutorials.junit.archunit.controller.BadOrderLookupController.rawStatus(java.lang.String)> calls method <com.ankurm.tutorials.junit.archunit.repository.OrderRepository.findStatus(java.lang.String)> in (BadOrderLookupController.java:25)
|
|
at com.tngtech.archunit.lang.ArchRule$Assertions.assertNoViolation(ArchRule.java:94)
|
|
at com.tngtech.archunit.lang.ArchRule$Assertions.check(ArchRule.java:86)
|
|
at com.tngtech.archunit.library.Architectures$LayeredArchitecture.check(Architectures.java:347)
|
|
at com.tngtech.archunit.junit.internal.ArchUnitTestDescriptor$ArchUnitRuleDescriptor.execute(ArchUnitTestDescriptor.java:168)
|
|
at com.tngtech.archunit.junit.internal.ArchUnitTestDescriptor$ArchUnitRuleDescriptor.execute(ArchUnitTestDescriptor.java:151)
|
|
at java.base/java.util.ArrayList.forEach(ArrayList.java:1604)
|
|
at java.base/java.util.ArrayList.forEach(ArrayList.java:1604)
|
|
|
|
[INFO] Results:
|
|
[ERROR] Tests run: 3, Failures: 1, Errors: 0, Skipped: 0
|
|
[INFO] BUILD FAILURE
|
|
|
|
Three things worth noticing in this message:
|
|
|
|
1. ArchUnit reports all THREE offending facts about the one bad class in a single
|
|
violation group: the constructor parameter, the field it gets assigned to, and
|
|
the actual method call that crosses the layer boundary. One bad wire gets
|
|
reported three ways because ArchUnit checks dependency *existence*, not just
|
|
call sites -- the field and the constructor parameter are both "access" on
|
|
their own, even on a line that never executes.
|
|
2. The file:line at the end of each fact (BadOrderLookupController.java:25) points
|
|
at real source positions ArchUnit extracted from the compiled .class file's
|
|
debug info, not from parsing the .java file.
|
|
3. "Priority: MEDIUM" is the rule's declared priority, not a severity the test
|
|
assigns at failure time -- layeredArchitecture() rules default to MEDIUM, and
|
|
a build can be configured to fail the whole run only above a given priority.
|