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

Junit test cases for javax Custom Validator

我正在 Spring 启动应用程序中使用 javax 验证 API 进行跨域验证。我有一个用户 bean,我必须验证 firstnamelastname 都不是 null/empty。此字段至少应有一个值。

我已经为此要求创建了自定义注释 (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;
}

NameMatch.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();
}

NameValidator.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;
    }
}

UserValidator.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");
        }
    }
}

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

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

使用 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);
  }

}

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

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

创建模拟

一种方法肯定是 Mockito(正如@rieckpil 提到的)。

如果你不想要那个,而实际上想要调用验证器,你可以有这样的东西:

@SpringBootTest
public class NameValidatorUnitTest {

  @Test
  public void whenExistingRootRole_thenFail()
  {
    AnnotationDescriptor<NameMatch> descriptor = new AnnotationDescriptor<NameMatch>( NameMatch.class );
    AnnotationFactory.create( descriptor );
    ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
    Validator validator =  factory.getValidator();


    User user = new User();
    user.setEmail("test@gmail.com");
    user.setPhone("12345678");

    Set<ConstraintViolation<User>> constraintViolations = validator.validate(user);
    if (constraintViolations.size() > 0) {
      for (ConstraintViolation<User> violation : constraintViolations) {
        System.out.println(violation.getMessage());
      }
    } else {
      System.out.println("Valid Object");
    }
    Assert.assertEquals(true, constraintViolations.size()>0);
  }
  

}