Test Your Java Architecture with ArchUnit- A Practical Example

Kunal Patil
3 min readOct 30, 2019

--

Testing Java Singleton Design Pattern using ArchUnit

I recently came across an article about the ArchUnit framework in Java Magazine and it instantly caught my attention. I thought of giving it a try as I am transitioning into Java Architect’s role. Even working as a Technical Lead, I had faced this challenge of ensuring that my team follows the solution architecture and guidelines prescribed to them and the resulting solution actually matches the architecture blueprint. As new developers join a development team or as the application maintenance team adds in fixes and features, they tend to diverge from the original designs over a period. I have also seen that usually, new team members look at the existing codebase to infer the design. And if they look at and follow the diverged part of the code, they will create even messier codebase. Even having software documentation in place, we know for real that there are very few developers who read the documentation and even fewer keep the documentation up-to-date. Also, chances of applying the documented design standards are left to the individuals who maintain the application.

Having had these practical experiences, when I read about ArchUnit, it felt like I found the right solution to the aforementioned problems. As ArchUnit is based on the popular JUnit testing framework, unit testing of architecture can be easily integrated into the existing CI/CD pipelines enforcing the architecture compliance in each release.

Java Design Patterns and ArchUnit

In order to try ArchUnit, I thought of testing one of the well known Java Design Patterns by the Gang of Four. I am sure that most of the Java architects use one of these design patterns more often than not in their solutions. So to start with, I tried testing the Singleton Pattern using the ArchUnit framework.

Singleton Pattern

Singleton Pattern ensures that only one instance of the singleton class ever exists and provides global access to that instance. You can find implementation details about the Singleton Pattern on this link.

Testing Singleton Pattern with ArchUnit

ArchUnit test cases for testing Singleton Pattern must test following assertions that make the Singleton Pattern:

  • The singleton class must have only private constructors
  • The singleton class must have a private, static field of its own type to hold the instance of the singleton class. The instance is created when the field is initialized
  • The singleton class must provide a public, static method that returns the reference to the instance

For a singleton`Class A` shown below:

package com.singletons;public class A {  private static A obj = new A();

private A() {}
public static A getInstance() { return obj; } public void doSomething() { System.out.println("Doing something"); }}

The ArchUnit test cases would look like the ones listed in below code snippet:

package singleton;import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.classes;import org.junit.Test;
import com.singletons.A;
import com.tngtech.archunit.core.domain.JavaClasses;
import com.tngtech.archunit.core.importer.ClassFileImporter;
import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.methods;
import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.fields;
public class SingletonTest {

JavaClasses classes = new ClassFileImporter().importPackages("com.singletons");
@Test
public void hasStaticMemberTest() {
fields()
.that()
.haveRawType(A.class)
.should().bePrivate()
.andShould().beStatic()
.because("'a singleton should have a static member of its own type'")
.check(classes);
}

@Test
public void privateConstructorOnlyTest() {
classes()
.should()
.haveOnlyPrivateConstructors()
.because("'The only way to get instance of singleton is to use getInstance() method'")
.check(classes);
}

@Test
public void hasStaticFactoryMethodTest() throws NoSuchMethodException, SecurityException {
methods()
.that()
.haveName(A.class.getMethod("getInstance").getName())
.should()
.haveRawReturnType(A.class)
.andShould().beStatic()
.andShould().bePublic()
.because("'a singleton should have a public static getInstance() method that always returns the same instance'")
.check(classes);
}

}

Sample Source Code

You can find a complete sample source code for above example can be found on Github.

Conclusion

I find ArchUnit very powerful in enforcing architecture compliance. The above example should suffice to showcase the capabilities of this testing framework and can be extended to encompass more test cases. I would recommend Java architects to read more on ArchUnit User Guide. I will look forward to your constructive feedback comments and suggestions on this topic.

--

--

Kunal Patil
Kunal Patil

No responses yet