我有一个“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;
}
}
和相应的接口类:
@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 "";
}
我希望能够编写一个单元测试类来测试该验证器中的直接逻辑。但似乎我用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());
}
我不想构建模拟模型来测试所有验证器。有没有办法创建一个单独的测试类,只是在一个验证器中直接测试逻辑而不使用任何其他模型类等?
您可以独立测试验证器。 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 );
}
您需要依赖于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;
}
}
}
我们可以模拟我们正在测试的类。由于注释只是一个接口,我们可以将具体实现作为初始化参数传递(您可以根据需要以任何方式执行以正确初始化测试)。然后你可以将模拟ConstraintValidatorContext
传递给你的isValid
方法。但是,您可能需要做一些额外的工作,具体取决于该方法的作用,如果它与您可能需要进行进一步模拟的上下文交互。