-
Notifications
You must be signed in to change notification settings - Fork 298
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
How do I execute the number check per JavaClass? #1103
Comments
You need to write an static importsimport static com.tngtech.archunit.base.DescribedPredicate.describe;
import static com.tngtech.archunit.core.domain.JavaModifier.PUBLIC;
import static com.tngtech.archunit.core.domain.properties.HasModifiers.Predicates.modifier;
import static com.tngtech.archunit.lang.conditions.ArchConditions.have;
import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.classes; ArchRule rule = classes()
.that().implement(IQueryHandler.class)
.should(have(describe("exactly one public method", javaClass ->
javaClass.getMethods().stream().filter(modifier(PUBLIC)).count() == 1
))); |
Oh, that's awesome! I thought I need to start with methods() since I was validating the methods; then I encounter the issue of counting the methods in a class (lost the context of class in the process). However, getMethods() also retrieves the interface method which I overridden. What's the correct way of excluding the super methods? I tried
but it cannot be filtered by modifier public anymore |
#1040 will probably introduce an API I thought that the |
Let me share you my objective of the test. I have created IQueryHandler
functional interface for all QueryHandler instances to implement. I want to
make sure that all QueryHandlers will only implement that method without
introducing more public methods.
Regards,
Emmett
|
Sorry, I had initially thought that the overwritten methods wouldn't matter and that the simple rule would be enough. My new suggestion is unfortunately more complex (but reports violations for individual methods): @ArchTest
void classes_that_implement_IQueryHandler_should_have_no_other_public_methods(JavaClasses classes) {
Set<JavaMethod> allowedMethods = Stream.of(IQueryHandler.class, Object.class)
.map(classes::get) // Make sure that Object is imported, or this throws an IllegalArgumentException!
.flatMap(javaClass -> javaClass.getAllMethods().stream().filter(modifier(PUBLIC)))
.collect(toSet());
methods()
.that().arePublic()
.and().areDeclaredInClassesThat().implement(IQueryHandler.class)
.should(new ArchCondition<JavaMethod>("implement IQueryHandler or extend from Object") {
@Override
public void check(JavaMethod method, ConditionEvents events) {
boolean notAllowed = allowedMethods.stream().noneMatch(allowedMethod ->
method.getName().equals(allowedMethod.getName()) &&
method.getParameterTypes().equals(allowedMethod.getParameterTypes())
);
if (notAllowed) {
String message = createMessage(method, "is public, but does not implement IQueryHandler");
events.add(violated(method, message));
}
}
})
.check(classes);
} |
Feature idea: Wouldn't it be nice if - boolean notAllowed = allowedMethods.stream().noneMatch(allowedMethod ->
- method.getName().equals(allowedMethod.getName()) &&
- method.getParameterTypes().equals(allowedMethod.getParameterTypes())
- );
- if (notAllowed) {
+ if (allowedMethods.stream().noneMatch(method::hasSameSignatureAs)) { ? |
Thank you. I faced issues with your code on fetching allowedMethods. I tried revising and sharing what worked:
|
Which issues did you face?
Will your rule ever catch violations in this way? You now allow every public method not only of |
I had added the warning Can you try my suggestion of #1103 (comment) again when you
(hoping that the import doesn't take too long in this case)? Because I still think that your way of collecting |
I thought that it should be allowed to override |
Are you sure that you've imported the right The error message above mention
whereas the last screenshot shows
(Furthermore, when using |
Hi @hankem , you were correct. I was importing the wrong package while I was copying pasting the code with censorship. After following your above comment, I'm afraid I still face a different issue in conditional matching. Furthermore, I do not understand why we need to get the allowedMethods from Object class. We don't need methods like I also find the fault in P.S. Apologies for the request, but could you remove the company name from your previous post? It was a missed from my side to censor the company name in the screenshot. |
I want to create a ArchUnit test to ensure no unnecessary public methods are created in my handlers.
A code violation is as follows:
I tried writing an assertion as follows:
But instead of ensuring there is only one public method in each class, it counts all public methods in the scanned JavaClasses.
The text was updated successfully, but these errors were encountered: