0

I was trying to follow the instructions in the article below trying to implement a simple annotation just to test if a string was a certain length as a test. My goal was to have this annotation thrown an exception at runtime if the String doesn't meet certain conditions.

https://dzone.com/articles/create-your-own-constraint-with-bean-validation-20

I'm able to add the annotation to the code and everything compiles & builds fine. However, no matter what I do when I try to invoke it from a unit test I cannot get the validation to run. I feel like I'm missing something obvious but I do not know what it is. Note that this is a Java SE backend service so no UI component. Let's take an example (which I know already exists of checking if a String is null or empty)

Here is the interface:

@Documented
@Constraint(validatedBy = {NotEmptyValidator.class})
@Target({METHOD, FIELD, CONSTRUCTOR, PARAMETER})
@Retention(RUNTIME)
public @interface NotEmpty {
    Class<?>[] groups() default {};
    String message() default "test message";
    Class<? extends Payload>[] payload() default {};
}

Here is the validator:

public class NotEmptyValidator implements ConstraintValidator<NotEmpty, String> {

@Override
public void initialize(final NotEmpty notEmpty) {
}

@Override
public boolean isValid(String notEmptyField, ConstraintValidatorContext constraintValidatorContext) {
    return !Strings.isNullOrEmpty(notEmptyField);

}

}

Note that retention is set to RUNTIME but it doesn't actually validate when I run a unit test on a String parameter that is an empty string.. how do I actually turn this validation on and get it to run?

for example if i have a random utility method

public static String testAnnotation(@NotEmpty final String foo) {
    return foo + "bar"
}

If I call that from a unit test even if the string is null or empty the validation doesn't run. Any help would be appreciated!

soeske18
  • 115
  • 1
  • 6
  • Can you also add the part of the code where you expect the validation to occur. That would be helpful. – mark_o Aug 30 '18 at 07:28
  • Hi Mark perhaps this is where my the gap of knowledge exists. Let me use a concrete example. I am testing this by creating a "NotEmpty" validation where all it does is test if a String is null or empty (I know something similar exists already but let's use this as an example) I am going to edit my example above with the code but when I use @NotEmpty in my code it compiles but the validation doesn't actually occur when running a unit test and passing an empty string. I feel like something obvious is missing here.. – soeske18 Aug 30 '18 at 17:04

1 Answers1

0

If I understand it correctly, you expect to receive a validation exception when you call your testAnnotation() method in way similar to this example:

public void doThings(){
    // some code
    testAnnotation("");
    //no exception is thrown and code proceed to next statements...
    // more code
}

if that's so, then the problem is that validation will not occur but itself. You either need to perform validation explicitly on some bean:

public void doValidationManually() {
    Validator validator = Validation.byDefaultProvider()
            .configure()
            .buildValidatorFactory()
            .getValidator();

    MyObj obj = new MyObj();
    // some more initialization...

    Set<ConstraintViolation<MyObj>> violations = validator.validate( obj );

    // make any decisions based on the set of violations.
}

The validator can be initialized outside the method and not created each time when validation is required.

In case of validation of method parameters, Bean Validation does not support static methods, but in case of non static method you would need to either again run validation manually:

public void doMethodValidationManually() throws NoSuchMethodException {
    ExecutableValidator validator = Validation.byDefaultProvider()
            .configure()
            .buildValidatorFactory()
            .getValidator().forExecutables();

    Method testAnnotationMethod = MyObj.class.getDeclaredMethod( "testAnnotation", String.class );

    MyObj obj = new MyObj();

    Set<ConstraintViolation<MyObj>> violations = validator.validateParameters(
            obj, // an object on which a method is expected to be called
            testAnnotationMethod, // the method which parameters we want to validate
            new Object[] { "" } // an array of parameters that we expect to pass to the method
    );

    // make any decisions based on the set of violations.
}

Or you should be running your code inside a container and in that case validation on your methods will be delegated and performed automatically by container. For more info on this see Bean Validation with CDI, or using Spring.

mark_o
  • 2,052
  • 1
  • 12
  • 18