javax 自定义验证器的 Junit 测试用例
Junit test cases for javax Custom Validator
我正在 Spring 启动应用程序中使用 javax 验证 API 进行跨域验证。我有一个用户 bean,我必须验证 firstname
和 lastname
都不是 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);
}
}
我正在 Spring 启动应用程序中使用 javax 验证 API 进行跨域验证。我有一个用户 bean,我必须验证 firstname
和 lastname
都不是 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);
}
}