ren*_*rof 7 testing validation spring hibernate-validator
我的实体有一个自定义的Hibernate验证器.我的一个验证器使用Autowired Spring @Repository.应用程序正常工作,我的存储库在我的验证器上成功自动装配.
问题是我找不到测试验证器的方法,因为我无法在其中注入我的存储库.
Person.class:
@Entity
@Table(schema = "dbo", name = "Person")
@PersonNameMustBeUnique
public class Person {
@Id
@GeneratedValue
@Column(name = "id", unique = true, nullable = false)
private Integer id;
@Column()
@NotBlank()
private String name;
//getters and setters
//...
}
Run Code Online (Sandbox Code Playgroud)
PersonNameMustBeUnique.class
@Target({ TYPE, ANNOTATION_TYPE })
@Retention(RUNTIME)
@Constraint(validatedBy = { PersonNameMustBeUniqueValidator.class })
@Documented
public @interface PersonNameMustBeUnique{
String message() default "";
Class<?>[] groups() default {};
Class<? extends javax.validation.Payload>[] payload() default {};
}
Run Code Online (Sandbox Code Playgroud)
验证者:
public class PersonNameMustBeUniqueValidatorimplements ConstraintValidator<PersonNameMustBeUnique, Person> {
@Autowired
private PersonRepository repository;
@Override
public void initialize(PersonNameMustBeUnique constraintAnnotation) { }
@Override
public boolean isValid(Person entidade, ConstraintValidatorContext context) {
if ( entidade == null ) {
return true;
}
context.disableDefaultConstraintViolation();
boolean isValid = nameMustBeUnique(entidade, context);
return isValid;
}
private boolean nameMustBeUnique(Person entidade, ConstraintValidatorContext context) {
//CALL REPOSITORY TO CHECK IF THE NAME IS UNIQUE
//ADD errors if not unique...
}
}
Run Code Online (Sandbox Code Playgroud)
上下文文件有一个验证器bean:
<bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean"/>
Run Code Online (Sandbox Code Playgroud)
再次,它工作正常,但我不知道如何测试它.
我的测试文件是:
@RunWith(MockitoJUnitRunner.class)
public class PersonTest {
Person e;
static Validator validator;
@BeforeClass
public static void setUpClass() {
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
validator = factory.getValidator();
}
@Test
public void name__must_not_be_null() {
e = new Person();
e.setName(null);
Set<ConstraintViolation<Person>> violations = validator.validate(e);
assertViolacao(violations, "name", "Name must not be null");
}
}
Run Code Online (Sandbox Code Playgroud)
我面临着非常相似的问题:如何编写具有自动装配配置 bean 的自定义验证器的纯单元测试?
我可以通过以下代码设法解决它(灵感来自用户abhishekrvce 的这个答案)。
这是带有@Autowired 配置bean 的自定义验证器的纯单元测试,它从配置文件(未在代码中显示)读取数据。
@Import({MyValidator.class})
@ContextConfiguration(classes = MyConfiguration.class, initializers = ConfigFileApplicationContextInitializer.class)
class MyValidatorTest {
private LocalValidatorFactoryBean validator;
@Autowired
private ConfigurableApplicationContext applicationContext;
@BeforeEach
void initialize() {
SpringConstraintValidatorFactory springConstraintValidatorFactory
= new SpringConstraintValidatorFactory(
applicationContext.getAutowireCapableBeanFactory());
validator = new LocalValidatorFactoryBean();
validator.setConstraintValidatorFactory(springConstraintValidatorFactory);
validator.setApplicationContext(applicationContext);
validator.afterPropertiesSet();
}
@Test
void isValid()
{
Set<ConstraintViolation<MyObject>> constraintViolations = validator
.validate(myObjectInstance);
assertThat(constraintViolations).hasSize(1);
}
}
Run Code Online (Sandbox Code Playgroud)
在@BeforeClass 上:
@BeforeClass
public static void setUpClass() {
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
validator = factory.getValidator();
}
Run Code Online (Sandbox Code Playgroud)
在你的测试中,你需要用你的模拟 bean 替换 bean:
myValidator.initialize(null);
BeanValidatorTestUtils.replaceValidatorInContext(validator, usuarioValidoValidator, e);
Run Code Online (Sandbox Code Playgroud)
做所有魔法的类:
public class BeanValidatorTestUtils {
@SuppressWarnings({ "rawtypes", "unchecked" })
public static <A extends Annotation, E> void replaceValidatorInContext(Validator validator,
final ConstraintValidator<A, ?> validatorInstance,
E instanceToBeValidated) {
final Class<A> anotacaoDoValidador = (Class<A>)
((ParameterizedType) validatorInstance.getClass().getGenericInterfaces()[0])
.getActualTypeArguments()[0];
ValidationContextBuilder valCtxBuilder = ReflectionTestUtils.<ValidationContextBuilder>invokeMethod(validator,
"getValidationContext");
ValidationContext<E> validationContext = valCtxBuilder.forValidate(instanceToBeValidated);
ConstraintValidatorManager constraintValidatorManager = validationContext.getConstraintValidatorManager();
final ConcurrentHashMap nonSpyHashMap = new ConcurrentHashMap();
ConcurrentHashMap spyHashMap = spy(nonSpyHashMap);
doAnswer(new Answer<Object>() {
@Override public Object answer(InvocationOnMock invocation) throws Throwable {
Object key = invocation.getArguments()[0];
Object keyAnnotation = ReflectionTestUtils.getField(key, "annotation");
if (anotacaoDoValidador.isInstance(keyAnnotation)) {
return validatorInstance;
}
return nonSpyHashMap.get(key);
}
}).when(spyHashMap).get(any());
ReflectionTestUtils.setField(constraintValidatorManager, "constraintValidatorCache", spyHashMap);
}
}
Run Code Online (Sandbox Code Playgroud)
小智 6
您可以在测试中将以下 bean 添加到您的 Spring Context 中:
@RunWith(SpringRunner.class)
@Import(LocalValidatorFactoryBean.class)
public class PersonTest {
@Autowired
private Validator validator;
{
validator.validate(new Person());
}
...
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
10428 次 |
| 最近记录: |