如何测试在java中实现ConstraintValidator的Validator?

问题描述 投票:7回答:2

我有一个“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());
    }

我不想构建模拟模型来测试所有验证器。有没有办法创建一个单独的测试类,只是在一个验证器中直接测试逻辑而不使用任何其他模型类等?

java validation testng bean-validation custom-validators
2个回答
7
投票

您可以独立测试验证器。 rub当然是initialize方法,因为它需要一个注释实例。你基本上有三个选择:

  1. 添加第二个初始化方法,该方法直接获取所需的参数。然后,您可以使用此方法初始化验证程序。如果您的测试位于同一个包中,您也可以使此方法只显示包
  2. 将测试注释放在测试类中并通过反射检索它,以便将其传递给initialize方法。
  3. 使用注释代理。这也是Hibernate Validator本身在内部使用的,以防通过XML配置约束或测试需要约束。 Hibernate Validator中有两个类,你可以使用AnnotationDescriptorAnnotationFactory。代码有点像这样:

--

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内部类,但出于测试目的,这应该没问题。当然,您也可以创建自己的代理框架。


0
投票

我使用了以下模式:

@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方法。但是,您可能需要做一些额外的工作,具体取决于该方法的作用,如果它与您可能需要进行进一步模拟的上下文交互。

© www.soinside.com 2019 - 2024. All rights reserved.