Search code examples
javaarchunit

Check if method B is also called when method A is called in Archunit


I'm trying to write a test to ensure all Hello instances which calls A method must also call B method (order is not important), where Hello class is a part of some 3rd party library. Is it possible to test it with ArchUnit?

class Hello {
  void A() {...}
  void B() {...}
  void C() {...}
}
Hello hello1 = new Hello();
hello1.A()

Hello hello2 = new Hello();
hello2.A()
hello2.B()

// hello1: fail
// hello2: success

This is what I have so far. If I'm in the right way, what I need is a callsBMethod() described predicate.

ArchRuleDefinition.methods().that().areDeclaredIn(Hello.class)
                .and().haveName("A")
                .should().onlyBeCalled().byCodeUnitsThat(<callsBMethod()>)

Solution

  • You can indeed use a custom predicate, e.g. this one (using import staticDescribedPredicate.describe):

        describe("call Hello.B()", codeUnit -> codeUnit.getCallsFromSelf().stream()
            .map(JavaAccess::getTarget)
            .anyMatch(target ->
                target.getOwner().isEquivalentTo(Hello.class)
                && target.getName().equals("B") && target.getParameterTypes().isEmpty()
            )
        )
    

    The predicate is basically for the code unit's calls, checking that some call's target (the method being called) is the right method (in the right class).