Search code examples
javaarchunit

How to check that a constructor is called in the right classes with ArchUnit?


Is there any way to enforce a rule like this one with ArchUnit :

@ArchTest
    static final ArchRule events_must_be_created_by_aggregates =
            noConstructors().that().areDeclaredInClassesThat().areAssignableTo(Event.class).should().beCalledInClassesThat().areNotAssignableFrom(Aggregate.class)
                    .because("the aggregate should manage its own lifecycle and events");

The issue here is that beCalledInClassesThat does not exists and I don't find anything that will allow me to implement such a test.


Solution

  • Whenever you miss something in the predefined fluent API, try to define a custom predicate/condition. In your case: does this work for you?

    @ArchTest
    static final ArchRule events_must_be_created_by_aggregates = constructors()
        .that().areDeclaredInClassesThat().areAssignableTo(Event.class)
        .should(new ArchCondition<JavaConstructor>("be called from aggregates") {
            @Override
            public void check(JavaConstructor constructor, ConditionEvents events) {
                for (JavaConstructorCall call : constructor.getCallsOfSelf()) {
                    if (!call.getOriginOwner().isAssignableTo(Aggregate.class)) {
                        events.add(SimpleConditionEvent.violated(call, call.getDescription()));
                    }
                }
            }
        });