I am a Spring/Java developer (primarily) and an advocate of unit testing. My co-workers have created some great blog posts on unit testing (especially for Java) for those who are also interested in the subject.
There is often a debate over what constitutes a unit test, an integration test, a system test, etc. But, most of us agree that tests keep you from going “off the rails” once a project becomes sufficiently complex.
However, I have found very few discussions on architectural tests. What keeps us from deviating wildly unintentionally from our original, planned architecture? And, after all, how many enterprise projects even keep the same architects from the beginning of the initiative to shelving and replacement?
In this blog, I introduce ArchUnit, a Java architecture test library for specifying and asserting architecture rules in plain Java. We’ll discuss how it works to mitigate architectural risks in developing quality enterprise applications.
Architectural Structure Debate & The Risks
Architectural structure is often another source of debate in an enterprise software team setting.
- How should the code be organized?
- What is the team going to do to keep it that way?
- Is an architect going to spend time checking that no team member is violating basic plans for the architecture of all the projects for which they are responsible?
- Who makes sure that the
System.out
calls are removed before we go to production? - After we have released to prod, but we had to track down that big bug last week where we threw tons of
sysouts
at it? - How do we know our cyclomatic complexity has gotten too large and it is time to refactor?
- Who makes sure that in the maintenance phase, someone doesn’t add calls from our model objects up to our controllers or views?
It is ultimately the responsibility of the architect or team lead. But, as deadlines creep up, we tend to “just get that last thing working.” Hopefully, there is time later to fix the “ugly bits,” but priorities are often not set by the architects or the teams writing the code.
You can imagine there are even more rules that are violated once the primary developers and architects move on and there is no direct management of the bug-fix and maintenance phases.
Introducing ArchUnit
ArchUnit is a great library that does a lot for you to mitigate these risks.
It is a Java unit testing framework, so you don’t need to learn a new tool. It has predefined classes that test for common things that go awry, but it is extensible so you can write your own rules and custom business checks that might only pertain to your company or even the specific project.
It uses the Java Reflection API to verify the current state of the code in either case. The ArchUnit team have provided great examples in their code on Github. I encourage you to check it out!
As an example, here is a common example provided by ArchUnit to catch sneaky layer violators…
ArchUnit/archunit-example/src/main/java/com/tngtech/archunit/example/persistence/layerviolation/DaoCallingService.java public class DaoCallingService implements ServiceInterface { public static final String violateLayerRules = "violateLayerRules"; public static final String violateLayerRulesTrickily = "violateLayerRulesTrickily"; ServiceViolatingLayerRules service; void violateLayerRules() { service.doSomething(); } void violateLayerRulesTrickily() { new SomeMediator(service).violateLayerRulesIndirectly(); } }
See It In Action
Here is a project where I demonstrate how I see ArchUnit’s library working in my projects going forward.
Advantages
The biggest advantage I see is the ability to build this group of architecture rules and use it again. Even if a new member joins the team, they will learn the rules quickly if they have repeatable unit tests that define the parameters.
As you find an edge case or something that had not been covered by testing, you can write tests to cover it. The tests run as you set it up, so you could make sure every check in is verified, nightly builds are verified or just when you move to production.
Final Thoughts
Over time, this could become an internal common library of architecture rules that you put in place at the beginning of a project to keep everyone on the same page from the beginning.
After all, less time spent checking things that can be automated means there is more time for things that cannot. I recommend you give ArchUnit a try.