Skip to content

Commit f78d5cf

Browse files
authored
Merge pull request #13 from aboutbits/validation_checking
add tool to check if parameter validation is enabled
2 parents 5ca5371 + 2a75007 commit f78d5cf

2 files changed

Lines changed: 179 additions & 0 deletions

File tree

src/main/java/it/aboutbits/springboot/testing/validation/core/BaseValidationAssert.java

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,23 @@
11
package it.aboutbits.springboot.testing.validation.core;
22

33
import it.aboutbits.springboot.toolbox.type.CustomType;
4+
import jakarta.validation.Valid;
45
import lombok.AccessLevel;
56
import lombok.Getter;
67
import lombok.NonNull;
78
import lombok.RequiredArgsConstructor;
89
import lombok.Setter;
910
import org.apache.logging.log4j.util.TriConsumer;
11+
import org.springframework.validation.annotation.Validated;
1012

13+
import java.util.Arrays;
1114
import java.util.HashSet;
1215
import java.util.Set;
1316
import java.util.function.BiConsumer;
1417
import java.util.function.Consumer;
1518

19+
import static org.assertj.core.api.Assertions.assertThat;
20+
1621
@RequiredArgsConstructor(access = AccessLevel.PROTECTED)
1722
public abstract class BaseValidationAssert<R extends BaseRuleBuilder<?>> {
1823
@Getter(AccessLevel.PROTECTED)
@@ -46,6 +51,43 @@ public <P> CallBuilder<R, P> of(@NonNull P parameterUnderTest) {
4651
return new CallBuilder<>(this);
4752
}
4853

54+
@SuppressWarnings("unused")
55+
public AnnotationChecker calling(
56+
@NonNull Class<?> classUnderTest,
57+
@NonNull String methodName,
58+
@NonNull Class<?>... methodParameterTypes
59+
) {
60+
return new AnnotationChecker(classUnderTest, methodName, methodParameterTypes);
61+
}
62+
63+
@RequiredArgsConstructor(access = AccessLevel.PRIVATE)
64+
public static final class AnnotationChecker {
65+
private final Class<?> classUnderTest;
66+
private final String methodName;
67+
private final Class<?>[] methodParameterTypes;
68+
69+
public void isEnabled() {
70+
assertThat(classUnderTest.isAnnotationPresent(Validated.class)).isTrue();
71+
72+
try {
73+
var method = classUnderTest.getMethod(methodName, methodParameterTypes);
74+
var parameter = method.getParameters()[method.getParameterCount() - 1];
75+
assertThat(parameter.isAnnotationPresent(Valid.class)).isTrue();
76+
} catch (NoSuchMethodException e) {
77+
throw new AssertionError(
78+
"Method \"%s(%s)\" not found in class \"%s\"".formatted(
79+
methodName,
80+
String.join(
81+
", ",
82+
Arrays.stream(methodParameterTypes).map(Class::getCanonicalName).toList()
83+
),
84+
classUnderTest.getCanonicalName()
85+
), e
86+
);
87+
}
88+
}
89+
}
90+
4991
@RequiredArgsConstructor(access = AccessLevel.PRIVATE)
5092
public static final class CallBuilder<R extends BaseRuleBuilder<?>, P> {
5193
private final BaseValidationAssert<R> parent;

src/test/java/it/aboutbits/springboot/testing/validation/ValidationAssertTest.java

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,10 @@
1515
import jakarta.validation.constraints.Positive;
1616
import jakarta.validation.constraints.PositiveOrZero;
1717
import lombok.With;
18+
import org.junit.jupiter.api.Nested;
1819
import org.junit.jupiter.api.Test;
1920
import org.springframework.lang.Nullable;
21+
import org.springframework.validation.annotation.Validated;
2022

2123
import java.math.BigDecimal;
2224
import java.math.BigInteger;
@@ -32,6 +34,7 @@
3234
import java.time.temporal.ChronoUnit;
3335

3436
import static it.aboutbits.springboot.testing.validation.ValidationAssertTest.TestValidationAssert.assertThatValidation;
37+
import static org.assertj.core.api.Assertions.assertThatCode;
3538
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
3639

3740
class ValidationAssertTest {
@@ -524,6 +527,97 @@ void propertyMissingRule_shouldFail() {
524527
.isCompliant());
525528
}
526529

530+
@Nested
531+
@SuppressWarnings("java:S5778") // Suppress the warning for lambdas with more than one exception cause
532+
class AnnotationChecking {
533+
@Test
534+
void givenValidatedClass_andValidParameter_shouldSucceed() {
535+
assertThatCode(
536+
() -> assertThatValidation().calling(
537+
ClassWithValidated.class,
538+
"someMethodWithValidParameter",
539+
String.class
540+
).isEnabled()
541+
).doesNotThrowAnyException();
542+
543+
assertThatCode(
544+
() -> assertThatValidation().calling(
545+
ClassWithValidated.class,
546+
"someMethodWithValidParameter",
547+
Long.class,
548+
String.class
549+
).isEnabled()
550+
).doesNotThrowAnyException();
551+
552+
assertThatCode(
553+
() -> assertThatValidation().calling(
554+
ClassWithValidated.class,
555+
"someMethodWithValidParameter",
556+
Long.class,
557+
Integer.class,
558+
String.class
559+
).isEnabled()
560+
).doesNotThrowAnyException();
561+
}
562+
563+
@Test
564+
void givenNotValidatedClass_shouldAlwaysFail() {
565+
assertThatExceptionOfType(AssertionError.class).isThrownBy(
566+
() -> assertThatValidation().calling(
567+
ClassWithoutValidated.class,
568+
"someMethodWithValidParameter",
569+
String.class
570+
).isEnabled()
571+
);
572+
573+
assertThatExceptionOfType(AssertionError.class).isThrownBy(
574+
() -> assertThatValidation().calling(
575+
ClassWithoutValidated.class,
576+
"someMethodWithValidParameter",
577+
Long.class,
578+
String.class
579+
).isEnabled()
580+
);
581+
582+
assertThatExceptionOfType(AssertionError.class).isThrownBy(
583+
() -> assertThatValidation().calling(
584+
ClassWithoutValidated.class,
585+
"someMethodWithValidParameter",
586+
Long.class,
587+
Integer.class,
588+
String.class
589+
).isEnabled()
590+
);
591+
592+
assertThatExceptionOfType(AssertionError.class).isThrownBy(
593+
() -> assertThatValidation().calling(
594+
ClassWithoutValidated.class,
595+
"someMethodWithoutValidParameter",
596+
String.class
597+
).isEnabled()
598+
);
599+
600+
assertThatExceptionOfType(AssertionError.class).isThrownBy(
601+
() -> assertThatValidation().calling(
602+
ClassWithoutValidated.class,
603+
"someMethodWithoutValidParameter",
604+
Long.class,
605+
String.class
606+
).isEnabled()
607+
);
608+
609+
assertThatExceptionOfType(AssertionError.class).isThrownBy(
610+
() -> assertThatValidation().calling(
611+
ClassWithoutValidated.class,
612+
"someMethodWithoutValidParameter",
613+
Long.class,
614+
Integer.class,
615+
String.class
616+
).isEnabled()
617+
);
618+
}
619+
}
620+
527621
private static SomeValidParameter getSomeValidParameter() {
528622
return new SomeValidParameter(
529623
// NotNull
@@ -654,4 +748,47 @@ public static TestValidationAssert assertThatValidation() {
654748
public static final class TestRuleBuilder extends BaseRuleBuilder<TestRuleBuilder> {
655749
}
656750
}
751+
752+
@SuppressWarnings({"java:S1186", "unused"}) // Suppress the "empty method body" warning
753+
@Validated
754+
public static class ClassWithValidated {
755+
public void someMethodWithValidParameter(@Valid String last) {
756+
}
757+
758+
public void someMethodWithValidParameter(Long first, @Valid String last) {
759+
}
760+
761+
public void someMethodWithValidParameter(Long first, Integer second, @Valid String last) {
762+
}
763+
764+
public void someMethodWithoutValidParameter(String last) {
765+
}
766+
767+
public void someMethodWithoutValidParameter(Long first, String last) {
768+
}
769+
770+
public void someMethodWithoutValidParameter(Long first, Integer second, String last) {
771+
}
772+
}
773+
774+
@SuppressWarnings({"java:S1186", "unused"}) // Suppress the "empty method body" warning
775+
public static class ClassWithoutValidated {
776+
public void someMethodWithValidParameter(@Valid String last) {
777+
}
778+
779+
public void someMethodWithValidParameter(Long first, @Valid String last) {
780+
}
781+
782+
public void someMethodWithValidParameter(Long first, Integer second, @Valid String last) {
783+
}
784+
785+
public void someMethodWithoutValidParameter(String last) {
786+
}
787+
788+
public void someMethodWithoutValidParameter(Long first, String last) {
789+
}
790+
791+
public void someMethodWithoutValidParameter(Long first, Integer second, String last) {
792+
}
793+
}
657794
}

0 commit comments

Comments
 (0)