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()>)
You can indeed use a custom predicate, e.g. this one (using import static
…DescribedPredicate.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).