Introduction
ArchUnit is a Java library for checking the architecture of your codebase through ordinary unit tests. It analyzes compiled bytecode to verify layering constraints, dependency rules, naming conventions, and more. Because tests run inside JUnit or TestNG, architecture violations surface alongside other test failures in your existing CI pipeline.
What ArchUnit Does
- Validates package dependency rules to enforce layered or hexagonal architectures
- Detects cyclic dependencies between packages or classes
- Enforces naming conventions such as requiring classes in a service package to end in Service
- Checks annotation usage patterns like ensuring all REST controllers carry specific annotations
- Integrates with JUnit 4, JUnit 5, and TestNG with zero additional infrastructure
Architecture Overview
ArchUnit imports Java classes from the classpath using an ASM-based bytecode reader, building an in-memory model of classes, methods, fields, and their relationships. The fluent rule API (classes().that()...should()...) compiles these constraints into predicates that are evaluated against the imported model. Custom rules can operate on the same model using the core API. The library caches class imports across tests in the same suite for performance.
Self-Hosting & Configuration
- Add
archunit-junit5(orarchunit-junit4) as a test dependency in Maven or Gradle - Annotate test classes with
@AnalyzeClasses(packages = "com.yourapp") - Write architecture rules using the fluent DSL and annotate them with
@ArchTest - Use the predefined
Architectures.layeredArchitecture()for standard layer checks - Run tests via
mvn testor./gradlew test— no additional tooling required
Key Features
- Plain Java rules — no external DSL, config files, or plugins needed
- Predefined rules for layered architecture, onion architecture, and slice isolation
- Extensible core API for writing custom checks on the class graph
- Freezing feature stores known violations in a baseline, letting teams fix issues incrementally
- Fast execution — bytecode analysis avoids starting the full application context
Comparison with Similar Tools
- Checkstyle/PMD — Focus on code style and simple bug patterns; ArchUnit validates structural architecture rules
- SonarQube — Server-based static analysis; ArchUnit runs inside unit tests with no external service
- jDepend — Measures package coupling metrics; ArchUnit lets you write expressive pass/fail rules
- Dependency-Check — Scans for vulnerable libraries; ArchUnit checks internal code structure
- Spring Modulith — Spring-specific module testing; ArchUnit is framework-agnostic
FAQ
Q: Does ArchUnit require a running application? A: No. ArchUnit analyzes compiled bytecode directly from the classpath without starting a Spring context or application server.
Q: How do I handle existing violations I cannot fix immediately?
A: Use the freezing feature: FreezingArchRule.freeze(rule). It stores current violations in a file and only fails on new ones.
Q: Can ArchUnit check Kotlin or Scala code? A: Yes. Since ArchUnit analyzes JVM bytecode, it works with any language that compiles to class files.
Q: Does ArchUnit slow down the test suite? A: Class import is typically fast (seconds for medium codebases) and cached across tests, adding minimal overhead.