ArchUnit - methods provided by an object

231 Views Asked by At

I'd like assert public API methods provided by an object instance.

Pseudocode sample:

Api api = Api.create();

assertThat(api)
  .hasPublicMethodNamed("foo")
  .doesNotHavePublicMethodNamed("bar");

Is it possible to accomplish this with ArchUnit?

2

There are 2 best solutions below

0
Manfred On BEST ANSWER

ArchUnit rules are based on classes, but you can ask your api instance for its class (api.getClass()).

Full example for JUnit4 (for JUnit5, just drop the ArchUnitRunner):

import com.tngtech.archunit.junit.AnalyzeClasses;
import com.tngtech.archunit.junit.ArchTest;
import com.tngtech.archunit.junit.ArchUnitRunner;
import com.tngtech.archunit.lang.ArchRule;
import org.junit.runner.RunWith;

import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.methods;

@RunWith(ArchUnitRunner.class)
@AnalyzeClasses(packagesOf = SO76536531.class)
public class SO76536531 {
    @ArchTest
    ArchRule public_API_naming_conventions =
        methods()
            .that().areDeclaredIn(getApi().getClass())
            .and().arePublic()
            .should().haveName("foo")
            // .orShould().haveName("foo2") // to allow others names, too
            .andShould().notHaveName("bar"); // redundant; just for illustration

    Object getApi() {
        return new Api();
    }

    static class Api {
        public void foo() {
        }

        // public void foo2() {
        // }

        public void bar() {
        }
    }
}

(Note that allowing for names foo and foo2 in this way will not guarantee that your API has both methods. But your question didn't specify what you want to obtain. Feel free to clarify if needed.)

0
Bash Cat On

Yes, use ArchRule:

ArchRule rule = classes().should(havePublicMethod("foo")).and(haveNoPublicMethod("bar"));
rule.check(classes);

It checks that all classes have a public method named “foo” and do not have a public method named “bar”. You can also use the ArchUnitRunner for JUnit tests.