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

}

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

谢谢!

4

3 回答 3

9

您不必为单元测试实现 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));
    }
}

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

于 2013-07-11T15:41:05.577 回答
2

当我想编写一个单元测试而不是 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;
  }
}
于 2016-07-01T08:50:48.910 回答
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());
    }

}

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

于 2013-07-11T18:03:44.090 回答