katana0815
katana0815

Reputation: 410

Spring Boot test entity field validation with custom validation

Setup:

Entity fields can be annotated with simple javax.validation constraints like @Positive.

@Entity
@Data
@Builder
public class Person {
    @Id
    @GeneratedValue
    private long id;

    @Column
    @Positive(message="not positive")
    private int age;
}

This can be tested quite easily:

public class PersonTest {

    private Validator validator;

    @BeforeEach
    public void before() {
        validator = Validation.buildDefaultValidatorFactory().getValidator();
    }

    @Test
    public void invalid_becauseNegativeAge() {
        Person uut = Person.builder().age(-1).build();
        Set<ConstraintViolation<Person>> actual = validator.validate(uut);
        assertThat(actual.iterator().next().getMessage()).isEqualTo("not positive");
    }
}

Now I add a custom validator to Person:

@Entity
@Data
@Builder
public class Person {
    @Id
    @GeneratedValue
    private long id;

    @Column
    @Positive(message="not old enough")
    private int age;

    @ComplexValueConstraint
    private String complexValue;
}

Custom annotation:

@Target({ ElementType.FIELD })
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = ComplexValueValidator.class)
public @interface ComplexValueConstraint {

    String message() default "too simple";    
    Class<?>[] groups() default {};    
    Class<? extends Payload>[] payload() default {};
}

Custom validator:

class ComplexValueValidator implements ConstraintValidator<ComplexValueConstraint, Person> {

    @Override
    public boolean isValid(final Person person, final ConstraintValidatorContext context) {
    String complexValue = person.getComplexValue();
    if (complexValue.length() < 5) {
        return false;
    }
    return true;
    }
}

Now, my test from above fails with a

javax.validation.UnexpectedTypeException: HV000030: No validator could be found for constraint 'ComplexValueConstraint' validating type 'java.lang.String'. Check configuration for 'complexValue'

How can I make this test to work again? I know I could test the validator in isolation, but then my simple annotations like @Positive would remain untested.

Is it because I create the validator in the test class manually? @Autowired won't work somehow.

Upvotes: 0

Views: 1758

Answers (1)

Scott Frederick
Scott Frederick

Reputation: 5125

You are declaring that ComplexValueValidator validates objects of type Person:

ComplexValueValidator implements ConstraintValidator<ComplexValueConstraint, Person>

but the annotation is applied to a field of type String instead of a field of type Person:

@ComplexValueConstraint
private String complexValue;

Hence the message that the constraint can not be applied to a java.lang.String.

Try changing complexValue to be of type Person instead of type String.

Upvotes: 1

Related Questions