Skip to main content
Exploring ideas, sharing knowledge
Hidden Peaks Unlocked!
Looks like you found the hidden peaks! Future posts are now visible.
Peaks Hidden Again
The future posts are hidden once more. You know how to find them again.

ArchUnit

Bet

A Java library for testing architectural rules as code

Software Architecture |

Metrics

Learning UX Potential Impact Ecosystem Market Standard Maintainability
Learning UX
4/5
Potential
3/5
Impact
3/5
Ecosystem
4/5
Market Standard
3/5
Maintainability
4/5

What is it

ArchUnit is a Java library for testing architectural rules. It allows you to define architectural constraints as unit tests, ensuring that your code follows the architecture you’ve designed. You can enforce rules like “controllers should only call services,” “entities should not depend on infrastructure,” or “all classes in the ‘api’ package should be annotated with @RestController.”

My Opinion

ArchUnit is architecture as code. Instead of writing architectural guidelines in a Confluence document that no one reads, you encode them as tests that run on every build. When someone violates the architecture, the build fails. This is how you maintain architectural integrity over time without endless code review debates.

The “Tests as Documentation” Approach

The genius of ArchUnit is that it treats architecture as a testable artifact. Your architectural rules are:

  • Version controlled alongside the code
  • Automatically enforced on every commit
  • Self-documenting through readable test names
  • Part of the CI/CD pipeline

You don’t need to argue about architectural violations in code reviews—the test fails, the violation is rejected. No politics, no negotiation.

The Fluent API

ArchUnit’s API is elegant and readable:

@AnalyzeClasses(packages = "com.myapp")
public class ArchitectureTest {
    @ArchTest
    static final ArchRule controllers_should_only_call_services =
        noClasses().that().resideInAPackage("..controller..")
            .should().dependOnClassesThat().resideInAPackage("..repository..");
}

You’re essentially writing tests in English. The intent is clear, and the error messages are helpful when rules are violated.

The “Over-Engineering” Risk

The danger is getting carried away. You can define extremely complex architectural rules that become brittle and hard to maintain. Every refactoring becomes a game of Whac-A-Mole with ArchUnit tests.

The key is focusing on rules that actually matter: layer boundaries, circular dependency prevention, naming conventions. Don’t encode every opinion as a test.

The “Java-Only” Limitation

ArchUnit is Java-only. If you have a polyglot architecture with JavaScript, Python, or Go services, ArchUnit can only test the Java code. You’ll need different tools for different languages, which defeats the purpose of unified architectural testing.

For Spring applications, ArchUnit is perfect. For microservices in multiple languages, it’s a partial solution.

The “Startup” Overhead

If you’re a startup building an MVP, ArchUnit is overkill. You don’t need to enforce strict architectural boundaries when the architecture is changing every week. ArchUnit is for projects with stable architecture and teams large enough that not everyone knows every design decision.

Conclusion

ArchUnit is a powerful tool for maintaining architectural integrity in Java/Spring projects. The ability to encode architecture as tests prevents the gradual degradation of code structure over time. But use it judiciously—focus on the rules that actually matter, and don’t let it become a barrier to necessary evolution. For projects outside the Java ecosystem, you’ll need alternative approaches.

Share this article