Frage

I've been reading the Hibernate docs about class validation tests and I did not found any solution to my "problem". I would like to test my custom validators. For example, let's say I have the following class:

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 */
}

And I want to check that every user is located in Barcelona city. For that, I would have my custom user validator implementation as follows:

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

}

I have no idea how to use this custom validator instead of the default one provided in the example and that only checks annotated field constraints and not more "business logic" ones. Any examples or clues on that?

Thanks!

War es hilfreich?

Lösung 3

I have finally found a solution:

@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());
    }

}

I have checked validation groups (any annotation with "groups" specified) and they are also working with the invokeValidator static method (by simply adding them after the errors parameter).

Andere Tipps

You don't have to implement the spring Validator for unit testing, just create a javax.validation.Validator instance for it.

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

And I would like use Validators to validate form or RPC request rather than some "Business Logic" in my expierence. They're not easy to use in Domain Layer from my point of view.

As I want to write a unit test instead of a Spring integration one I ended up in the following (even working in a Spring context):

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;
  }
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top