ArchUnit practice: Check for forgetting to add method annotations that are important in implementation

//Execution environment
* AdoptOpenJDK 11.0.9.1+1
* Spring Boot 2.4.0
* JUnit 5.7.0
* ArchUnit 0.14.1

Architectural test motivation

I want to secure important application-specific implementation rules.

Implementation image of handler method

//Blog New Post Endpoint
// `EDITOR`Only authorized users can use the endpoint
@Auth(Role.EDITOR)
@PostMapping("/api/blogs")
public Map<String, Object> postBlog(@RequestBody final BlogCreateForm form) {
    // ...
}

Architecture test implementation

package com.example;
 
import com.example.presentation.Auth;
import com.tngtech.archunit.base.DescribedPredicate;
import com.tngtech.archunit.core.domain.JavaClasses;
import com.tngtech.archunit.core.domain.JavaMethod;
import com.tngtech.archunit.core.importer.ClassFileImporter;
import com.tngtech.archunit.core.importer.ImportOption;
import com.tngtech.archunit.lang.ArchCondition;
import com.tngtech.archunit.lang.ConditionEvents;
import com.tngtech.archunit.lang.SimpleConditionEvent;
import org.junit.jupiter.api.Test;
import org.springframework.web.bind.annotation.*;

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

class ArchitectureTest {

    //Class to be inspected
    private static final JavaClasses CLASSES =
            new ClassFileImporter()
                    .withImportOption(ImportOption.Predefined.DO_NOT_INCLUDE_TESTS)
                    .importPackages("com.example");

    @Test
Be sure to authenticate and authorize the void API endpoint() {
        methods()
            .that(new DescribedPredicate<>("are request handler") {
                /**
                 * @param method Method of inspected class
                 * @true if it is a return handler method
                 */
                @Override
                public boolean apply(JavaMethod method) {
                    return method.isAnnotatedWith(RequestMapping.class)
                        || method.isAnnotatedWith(GetMapping.class)
                        || method.isAnnotatedWith(PostMapping.class)
                        || method.isAnnotatedWith(PutMapping.class)
                        || method.isAnnotatedWith(PatchMapping.class)
                        || method.isAnnotatedWith(DeleteMapping.class);
                }
            })
            .should(new ArchCondition<>("be annotated with @Auth") {
                @Override
                public void check(JavaMethod method, ConditionEvents events) {
                    if (! method.isAnnotatedWith(Auth.class)) {
                        //Notify implementation rule violation
                        events.add(
                            SimpleConditionEvent.violated(method, String.format(
                                "`%s` is not annotated with @Auth.", method.getFullName()))
                        );
                    }
                }
            })
            .check(CLASSES);
    }
}

Recommended Posts

ArchUnit practice: Check for forgetting to add method annotations that are important in implementation
[Java] Is it unnecessary to check "identity" in the implementation of the equals () method?
About characters that are completed in method arguments
Features that are likely to enter Java 10 for now