Hibernate验证器单元测试

3

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

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"); 
         }
    }

}

我不知道如何使用此自定义验证器,而不是提供在示例中仅检查注释字段约束而不是更多的“业务逻辑”约束的默认验证器。 有关此问题的示例或提示吗?

谢谢!


Spring的版本是多少? - Yugang Zhou
嗨 @Hippoom,我正在使用Spring 3.2.3.RELEASE。我发现了这个例子(https://dev59.com/mOo6XIcBkEYKwwoYQiTQ),但我认为这不支持验证组,虽然我的示例中没有,但在某些时候可能也需要。 - jarandaf
3个回答

10

在进行单元测试时,您无需实现Spring验证器,只需为其创建一个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));
    }
}

根据我的经验,我更倾向于使用验证器来验证表单或RPC请求,而不是在业务逻辑中进行验证。在我看来,在领域层中使用它们并不容易。


如果您正在测试控制器上的某些验证,那么您还需要在控制器上注入此验证器... - renanleandrof
当使用Spring 3.2.0及以上版本时,您可以在ModelAttribute上使用@Valid,因此无需实现自定义Spring验证器。 - Yugang Zhou
我不确定我正确理解了你的回答,但我想说这只检查javax.validation注释而不是自定义的spring验证器,而这正是我的情况(请参见http://static.springsource.org/spring/docs/3.2.x/spring-framework-reference/html/validation.html)。我的意思是,在上面的示例中,它只会检查非空/大小约束,但不会检查字段城市中唯一接受的值是“巴塞罗那”。 - jarandaf

3

由于我想编写单元测试而不是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(true));
    // 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;
  }
}

2
我终于找到了一个解决方案:

@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静态方法一起使用(只需在错误参数后添加它们)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接