javaunit-testingarchunit

ArchUnit - methods provided by an object


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?


Solution

  • 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.)