Hibernate验证器单元测试

时间:2013-07-11 11:09:21

标签: hibernate spring-mvc hibernate-validator spring-validator

我一直在阅读关于类验证测试的Hibernate docs,但我没有找到解决我的“问题”的方法。我想测试我的自定义验证器。例如,假设我有以下类:

public class User {

    @NotEmpty(message = "{username.notSpecified}")
    private String username;

    @NotEmpty
    @Size(min = 6, message = "{password.tooShort")
    private String password;

    @NotEmpty(message = "{city.notSpecified}")
    private String city;

    /* getters & setters omitted */
}

我想检查每个用户是否位于巴塞罗那市。为此,我将自定义用户验证器实现如下:

public class UserValidator implements Validator {

    @Autowired 
    private Validator validator;

    @Override
    public boolean supports(Class<?> clazz) {
        return User.class.equals(clazz);
    }

    @Override
    public void validate(Object target, Errors errors) {
         validator.validate(target,errors);
         User user = (User) target;
         if(!(user.getCity().equals("Barcelona"))){
              errors.rejectValue("city", "city.notValid", "Invalid city"); 
         }
    }

}

我不知道如何使用这个自定义验证器而不是示例中提供的默认验证器,并且只检查带注释的字段约束而不是更多“业务逻辑”约束。关于它的任何例子或线索?

谢谢!

3 个答案:

答案 0 :(得分:5)

您不必为单元测试实现spring Validator,只需为它创建一个javax.validation.Validator实例。

import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;

import java.util.*;

import javax.validation.*;

import org.junit.*;

public class ApplierDtoUnitTests {

    private Validator validator = Validation.buildValidatorFactory().getValidator();
    private ApplierDto target = new ApplierDto();


    @Test
    public void brokenIfNullNameGiven() throws Exception {

        target.setName(null);

        Set<ConstraintViolation<ApplierDto>> constraintViolations = validator
            .validate(target);
        assertThat("unexpected size of constraint violations",
            constraintViolations.size(), equalTo(1));
    }
}

我想在我的expierence中使用Validators来验证表单或RPC请求,而不是某些“业务逻辑”。从我的角度来看,它们在域层中并不容易使用。

答案 1 :(得分:1)

我终于找到了解决方案:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"/test-applicationContext.xml"})
public class UserValidatorTest {

    private static Logger logger = Logger.getLogger(UserValidatorTest.class);

    @Autowired
    private UserValidator validator;  //my custom validator, bean defined in the app context

    @Test
    public void testUserValidator(){
        User user = new User("name", "1234567", "Barcelona");
        BindException errors = new BindException(user, "user");
        ValidationUtils.invokeValidator(validator, user, errors);
        Assert.assertFalse(errors.hasErrors());
    }

}

我检查了验证组(指定了“groups”的任何注释),并且它们也使用invokeValidator静态方法(只需在errors参数之后添加它们)。

答案 2 :(得分:1)

由于我想编写一个单元测试而不是Spring集成测试,我最终会在下面进行编写(甚至在Spring上下文中工作):

public class MyValidatorTest {

  private Validator validator;

  @Test
  public void check() {
    TestBean bean = new TestBean();
    bean.setMember(...);

    Errors actual = invokeValidator(bean);

    assertThat(actual.hasErrors(), is(!valid));
    // more assertions here
  }

  @Before
  public void createValidator() {
    // the validator to test is found be the @Constraint(validatedBy=...) in @MyValidation
    validator = new SpringValidatorAdapter(Validation.buildDefaultValidatorFactory().getValidator());
  }

  private Errors invokeValidator(Object bean) {
    BeanPropertyBindingResult errors = new BeanPropertyBindingResult(bean, "bean");
    ValidationUtils.invokeValidator(validator, bean, errors);
    return errors;
  }

  private static class TestBean {
    @MyValidation
    private AnyType member;
  }
}