I\'m using Spring Validator implementations to validate my object and I would like to know how do you write a unit test for a validator like this one:
public
Here is the code that shows how to unit test for validation:
1) The main Validator class for which one needs to write unit test:
public class AddAccountValidator implements Validator {
private static Logger LOGGER = Logger.getLogger(AddAccountValidator.class);
public boolean supports(Class clazz) {
return AddAccountForm.class.equals(clazz);
}
public void validate(Object command, Errors errors) {
AddAccountForm form = (AddAccountForm) command;
validateFields(form, errors);
}
protected void validateFields(AddAccountForm form, Errors errors) {
if (!StringUtils.isBlank(form.getAccountname()) && form.getAccountname().length()>20){
LOGGER.info("Account Name is too long");
ValidationUtils.rejectValue(errors, "accountName", ValidationUtils.TOOLONG_VALIDATION);
}
}
}
2) Utility class supporting 1)
public class ValidationUtils {
public static final String TOOLONG_VALIDATION = "toolong";
public static void rejectValue(Errors errors, String fieldName, String value) {
if (errors.getFieldErrorCount(fieldName) == 0){
errors.rejectValue(fieldName, value);
}
}
}
3) Here is the unit test:
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import org.junit.Test;
import org.springframework.validation.BeanPropertyBindingResult;
import org.springframework.validation.Errors;
import com.bos.web.forms.AddAccountForm;
public class AddAccountValidatorTest {
@Test
public void validateFieldsTest_when_too_long() {
// given
AddAccountValidator addAccountValidator = new AddAccountValidator();
AddAccountForm form = new AddAccountForm();
form.setAccountName(
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa1");
Errors errors = new BeanPropertyBindingResult(form, "");
// when
addAccountValidator.validateFields(form, errors);
// then
assertEquals(
"Field error in object '' on field 'accountName': rejected value [aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa1]; codes [toolong.accountName,toolong.java.lang.String,toolong]; arguments []; default message [null]",
errors.getFieldError("accountName").toString());
}
@Test
public void validateFieldsTest_when_fine() {
// given
AddAccountValidator addAccountValidator = new AddAccountValidator();
AddAccountForm form = new AddAccountForm();
form.setAccountName("aaa1");
Errors errors = new BeanPropertyBindingResult(form, "");
// when
addAccountValidator.validateFields(form, errors);
// then
assertNull(errors.getFieldError("accountName"));
}
}
It is a really straight forward test without any mock. (just the error-object creation is a bit tricky)
@Test
public void testValidationWithValidAddress() {
AdressValidator addressValidator = new AddressValidator();
CustomValidator validatorUnderTest = new CustomValidator(adressValidator);
Address validAddress = new Address();
validAddress.set... everything to make it valid
Errors errors = new BeanPropertyBindingResult(validAddress, "validAddress");
validatorUnderTest.validate(validAddress, errors);
assertFalse(errors.hasErrors());
}
@Test
public void testValidationWithEmptyFirstNameAddress() {
AdressValidator addressValidator = new AddressValidator();
CustomValidator validatorUnderTest = new CustomValidator(adressValidator);
Address validAddress = new Address();
invalidAddress.setFirstName("")
invalidAddress.set... everything to make it valid exept the first name
Errors errors = new BeanPropertyBindingResult(invalidAddress, "invalidAddress");
validatorUnderTest.validate(invalidAddress, errors);
assertTrue(errors.hasErrors());
assertNotNull(errors.getFieldError("firstName"));
}
BTW: if you really want to make it more complicate and make it complicate by a mock, then have a look at this Blog, they use a two mocks, one for the object to test (ok, this is useful if you can not create one), and a second for the Error
object (I think this is more complicated the it must be.)