javax 自定义验证器的 Junit 测试用例

use*_*519 2 java validation hibernate-validator spring-boot junit5

我正在 Spring Boot 应用程序中使用 javax 验证 API 进行跨字段验证。我有一个 User bean,我必须验证firstname两者lastname为空/空。该字段至少有一个应该有值。

我为此需求创建了自定义注释 ( NameMatch.java) 和自定义验证器 ( )。NameValidator.java

@NameMatch(first = "firstname", second = "lastname", message = "The first and lastname can't be null")
public class User  {

    private String firstname;

    private String lastname;

    @NotNull
    @Email
    private String email;

    @NotNull
    private String phone;
}
Run Code Online (Sandbox Code Playgroud)

名称匹配.java

@Target({TYPE, ANNOTATION_TYPE})
@Retention(RUNTIME)
@Constraint(validatedBy = NameValidator.class)
@Documented
public @interface NameMatch
{
    String message() default "{constraints.fieldmatch}";

    Class<?>[] groups() default {};

    Class<? extends Payload>[] payload() default {};

    /**
     * @return The first field
     */
    String first();

    /**
     * @return The second field
     */
    String second();
}
Run Code Online (Sandbox Code Playgroud)

名称验证器.java

public class NameValidator implements ConstraintValidator<NameMatch, Object>
{
    private String firstFieldName;
    private String secondFieldName;

    @Override
    public void initialize(final NameMatch constraintAnnotation)
    {
        firstFieldName = constraintAnnotation.first();
        secondFieldName = constraintAnnotation.second();
    }

    @Override
    public boolean isValid(final Object value, final ConstraintValidatorContext context)
    {
        boolean isValidName = false;
        try
        {
            final Object firstName = BeanUtils.getProperty(value, firstFieldName);
            final Object lastName = BeanUtils.getProperty(value, secondFieldName);
            
            // Validation logic

        }
        catch (final Exception ignore)
        {
        }
        return isValidName;
    }
}
Run Code Online (Sandbox Code Playgroud)

用户验证器.java

public class UserValidator
{
    public void isValidUser()
    {
        //Create ValidatorFactory which returns validator
        ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
         
        //It validates bean instances
        Validator validator = factory.getValidator();
 
        User user = new User();
        user.setEmail("test@gmail.com");
        user.setPhone("12345678") 
 
        //Validate bean
        Set<ConstraintViolation<User>> constraintViolations = validator.validate(user);
 
        //Show errors
        if (constraintViolations.size() > 0) {
            for (ConstraintViolation<User> violation : constraintViolations) {
                System.out.println(violation.getMessage());
            }
        } else {
            System.out.println("Valid Object");
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我必须为自定义验证器类编写 JUnit 测试用例。我探索了 hibernate 验证器文档,但找不到通过 JUnit 调用自定义验证器方法的方法。有人可以帮忙为上述场景编写 JUnit 测试用例吗?

rie*_*pil 8

NameValidator有公共方法,因此您可以实例化一个对象并像任何其他公共方法一样编写单元测试。

使用 Mockito 进行的可能的 JUnit 5 测试如下所示:

@ExtendWith(MockitoExtension.class)
class NameValidatorTest {

  @Mock
  private NameMatch nameMatch;

  @Mock
  private ConstraintValidatorContext constraintValidatorContext;

  @Test
  public void testIsValid() {

    when(nameMatch.first()).thenReturn("firstname");
    when(nameMatch.second()).thenReturn("lastname");


    NameValidator nameValidator = new NameValidator();
    nameValidator.initialize(nameMatch);

    User user = new User();
    user.setFirstname("Duke");
    user.setLastname("Duke");

    boolean result = nameValidator.isValid(user, constraintValidatorContext);
    assertTrue(result);
  }

}
Run Code Online (Sandbox Code Playgroud)

根据您的需要,ConstraintValidatorContext您可能还想模拟方法或稍后验证是否调用了特定方法。

如果您不使用 JUnit 5,则可以将代码调整为不使用 JUnit 5MockitoExtension并使用Mockito.mock().