goe*_*goe 10 java validation testng custom-validators bean-validation
我有一个"AllowedValuesValidator.java"类:
public class AllowedValuesValidator implements ConstraintValidator<AllowedValues, String> {
String[] values;
String defaultValue;
@Override
public void initialize(AllowedValues constraintAnnotation) {
values = constraintAnnotation.allowedValues();
defaultValue = constraintAnnotation.defaultValue();
}
@Override
public boolean isValid(String value, ConstraintValidatorContext context) {
if (!StringUtils.isEmpty(defaultValue) && StringUtils.isEmpty(value)) {
value = defaultValue;
}
if (!StringUtils.isEmpty(value) && !Arrays.asList(values).contains(value)) {
return false;
}
return true;
}
}
Run Code Online (Sandbox Code Playgroud)
和相应的接口类:
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = AllowedValuesValidator.class)
public @interface AllowedValues {
String message();
String fieldName();
int fieldNumber();
String[] allowedValues() default {"Y", "N"};
String defaultValue() default "";
}
Run Code Online (Sandbox Code Playgroud)
我希望能够编写一个单元测试类来测试该验证器中的直接逻辑.但似乎我用Google搜索的大多数地方给出了测试类的示例,其中我们基本上测试给定Model类的所有验证器,例如:
@BeforeClass
public static void setup() {
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
validator = factory.getValidator();
}
@Test
public void testEmailExistsIncorrect() {
Set<constraintviolation<usercredentialsdto>> violations = validator
.validate(credentials, UserCredentialsDto.class);
Assert.assertEquals(1, violations.size());
}
Run Code Online (Sandbox Code Playgroud)
我不想构建模拟模型来测试所有验证器.有没有办法创建一个单独的测试类,只是在一个验证器中直接测试逻辑而不使用任何其他模型类等?
您可以独立测试验证器.rub当然是initialize方法,因为它需要一个注释实例.你基本上有三个选择:
AnnotationDescriptor和AnnotationFactory.代码有点像这样:-
private AllowedValues createAnnotation(String[]values, String defaultValue) {
AnnotationDescriptor<AllowedValues> descriptor = new AnnotationDescriptor<AllowedValues>( AllowedValues.class );
descriptor.setValue( "values", values );
descriptor.setValue( "defaultValue", defaultValue );
return AnnotationFactory.create( descriptor );
}
Run Code Online (Sandbox Code Playgroud)
您需要依赖于Hibernate Validator内部类,但出于测试目的,这应该没问题.当然,您也可以创建自己的代理框架.
我使用了以下模式:
@RunWith(MockitoJUnitRunner.class)
public class AllowedValuesValidatorTest {
@Mock
AllowedValuesValidator allowedValuesValidator;
@Mock
ConstraintValidatorContext constraintValidatorContext;
@Before
public void setUp() {
doCallRealMethod().when(allowedValuesValidator).initialize(any());
when(allowedValuesValidator.isValid(any(), any())).thenCallRealMethod();
AllowedValuesValidatorTestClass testClass = new AllowedValuesValidatorTestClass();
allowedValuesValidator.initialize(testClass);
}
@Test
public void testIsValidWithValidValues() {
assertTrue(allowedValuesValidator.isValid("Value", constraintValidatorContext));
}
private class AllowedValuesValidatorTestClass implements AllowedValues {
@Override
public String message() {
return "Test Message";
}
@Override
public Class<?>[] groups() {
return new Class[]{};
}
@Override
public Class<? extends Payload>[] payload() {
return new Class[]{};
}
@Override
public Class<? extends Annotation> annotationType() {
return AllowedValues.class;
}
}
}
Run Code Online (Sandbox Code Playgroud)
我们可以模拟我们正在测试的类。由于注释只是一个接口,我们可以将具体实现作为参数传递给初始化(为了正确初始化您的测试,您可以按照您需要的任何方式进行操作)。然后,您可以将模拟传递ConstraintValidatorContext给您的isValid方法。但是,根据该方法的作用,您可能需要做一些额外的工作,如果它与上下文交互,您可能需要做一些进一步的模拟。
注解:
@Documented
@Constraint(validatedBy = NoWhitespacesValidator.class)
@Target({ FIELD })
@Retention(RUNTIME)
public @interface NoWhitespaces {
String message() default "Not valid";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
Run Code Online (Sandbox Code Playgroud)
验证器:
public class NoWhitespacesValidator implements ConstraintValidator<NoWhitespaces, String> {
@Override public boolean isValid(String value, ConstraintValidatorContext context) {
return !value.contains(" ");
}
}
Run Code Online (Sandbox Code Playgroud)
测试用例:
class NoWhitespacesTest {
private NoWhitespacesValidator validator = new NoWhitespacesValidator();
@Nested
class NoWhitespaceValidFlow {
@Test
void isValid_shouldReturnTrue_whenNoWhitespaces() {
assertTrue(isValid(""));
assertTrue(isValid("foo.bar"));
}
}
@Nested
class NoWhitespacesInvalidFlow {
@Test
void isValid_shouldReturnFalse_whenAtLeastOneWhitespace() {
assertFalse(isValid(" "));
assertFalse(isValid("foo bar"));
assertFalse(isValid(" foo"));
assertFalse(isValid("foo "));
}
}
private boolean isValid(String value) {
return validator.isValid(value, null);
}
}
Run Code Online (Sandbox Code Playgroud)
小智 5
正如@Rammgarot建议的那样,它工作得很好,但是如果我们更改他的代码,例如验证规则必须是下一个:“没有空格”并且必须以“stack”一词开头
NoWhitesSpace.java
@Documented
@Constraint(validatedBy = NoWhitespacesValidator.class)
@Target({ FIELD })
@Retention(RUNTIME)
public @interface NoWhitesSpace {
String value() default "stack";
String message() default "Not valid";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
Run Code Online (Sandbox Code Playgroud)
NoWhitespacesValidator.java
public class NoWhitespacesValidator implements ConstraintValidator<NoWhitesSpace, String> {
String prefix;
public void initialize(NoWhitesSpace constraint) {
prefix = constraint.value();
}
public boolean isValid(String value, ConstraintValidatorContext context) {
boolean result = !value.contains(" ") && value.startsWith(prefix);
return result;
}
}
Run Code Online (Sandbox Code Playgroud)
测试不会通过,代码将生成 NullPointerException。
对我来说,我通过模拟找到了解决方案。
-> Customer 是一个简单的类实体,具有 fields 、 setter 和 getter 。
NoWhitespacesValidatorTest.java
class NoWhitespacesValidatorTest {
private NoWhitesSpace noWhitesSpace = mock(NoWhitesSpace.class);
private ConstraintValidatorContext constraintValidatorContext = mock(ConstraintValidatorContext.class);
@Test
public void itShouldBeValidWhenItStartsWithPrefixAndWithoutWhiteSpace(){
when(noWhitesSpace.value()).thenReturn("stack");
NoWhitespacesValidator noWhitespacesValidator=new NoWhitespacesValidator();
noWhitespacesValidator.initialize(noWhitesSpace);
Customer customer = new Customer();
customer.setCourseCode("stack");
boolean result = noWhitespacesValidator.isValid(customer.getCourseCode(),constraintValidatorContext);
assertTrue(result);
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
8872 次 |
| 最近记录: |