Я работаю над тестами JUnit для валидаторов ограничений с зависимостями. Я создал пользовательский ConstraintValidatorFactory
, который имеет доступ к макетам Mockito, и в основном все работает.
Чтобы уменьшить накладные расходы на инициализацию, я хотел, чтобы ValidatorFactory
статически инициализировался только один раз в пользовательском правиле JUnit и для каждогопри выполнении теста будет использоваться новый ValidatorContext
.
К сожалению, валидатор ограничения для конкретной «точки валидации» запрашивается только один раз из фабрики валидатора ограничения, независимо от используемого контекста валидатора (см. пример кода ниже).
Я бы ожидал, что при использовании контекста с пользовательской фабрикой валидаторов ограничений все валидаторы ограничений всегда запрашиваются из этой фабрики и не разделяются во всех контекстах. Я протестировал двух провайдеров проверки бинов, и оба они ведут себя одинаково, поэтому, вероятно, он работает как задумано. Но тогда каков типичный вариант использования фабрики валидаторов пользовательских ограничений внутри контекста?
public class ValidatorContextTest {
@Rule
public final MockitoRule mockitoRule = MockitoJUnit.rule().strictness(Strictness.STRICT_STUBS);
@Mock
private ConstraintValidatorFactory constraintValidatorFactory;
@Test
public void test() {
final ValidatorFactory validatorFactory = Validation.buildDefaultValidatorFactory();
when(constraintValidatorFactory.getInstance(TestBeanAnnotationValidator.class))
.thenReturn(new TestBeanAnnotationValidator());
for (int i = 0; i < 2; i++) {
final Validator validator = validatorFactory
.usingContext()
// assumption: constraint validators instantiated by this factory are "bound" to this very context
.constraintValidatorFactory(constraintValidatorFactory)
.getValidator();
validator.validate(new TestBean());
}
// fails with "Wanted 2 times, but was 1 time"
verify(constraintValidatorFactory, times(2)).getInstance(TestBeanAnnotationValidator.class);
}
@TestBeanAnnotation
private static class TestBean {
// no extras
}
@Constraint(validatedBy = {TestBeanAnnotationValidator.class})
@Documented
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface TestBeanAnnotation {
String message() default "Test message";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
public static class TestBeanAnnotationValidator implements ConstraintValidator<TestBeanAnnotation, TestBean> {
// fields, constructor etc.
public void initialize(TestBeanAnnotation testBeanAnnotation) {
// NOP
}
public boolean isValid(TestBean testBean, ConstraintValidatorContext constraintValidatorContext) {
return false;
}
}
}